ダイジェストを強制するための $scope がない場合、AngularJS、Jasmine 2.0 で Promise を解決するにはどうすればよいですか?
-
21-12-2019 - |
質問
約束しているようです 強制的に実行しない限り、Angular/Jasmine テストでは解決されません。 $scope.$digest()
. 。これは愚かな IMO ですが、問題ありません。該当する場所 (コントローラー) では機能します。
私が今いる状況は、アプリケーション内のスコープをあまり気にしないサービスがあり、サーバーからデータを返すだけですが、Promiseが解決していないようです。
app.service('myService', function($q) {
return {
getSomething: function() {
var deferred = $q.defer();
deferred.resolve('test');
return deferred.promise;
}
}
});
describe('Method: getSomething', function() {
// In this case the expect()s are never executed
it('should get something', function(done) {
var promise = myService.getSomething();
promise.then(function(resp) {
expect(resp).toBe('test');
expect(1).toEqual(2);
});
done();
});
// This throws an error because done() is never called.
// Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
it('should get something', function(done) {
var promise = myService.getSomething();
promise.then(function(resp) {
expect(resp).toBe('test');
expect(1).toEqual(2);
done();
});
});
});
この機能をテストする正しい方法は何ですか?
編集:参考までに解決策。どうやら、サービスが $rootScope を使用していない場合でも、$rootScope を挿入してダイジェストする必要があるようです。
it('should get something', function($rootScope, done) {
var promise = myService.getSomething();
promise.then(function(resp) {
expect(resp).toBe('test');
});
$rootScope.$digest();
done();
});
解決
テストに$rootScope
を挿入し、$digest
をトリガーする必要があります。
他のヒント
$ ROOTSCOPEが常にあります。
を使用してください。inject(function($rootScope){
myRootScope=$rootScope;
})
....
myRootScope.$digest();
. それで私は午後中ずっとこれと格闘しています。この投稿を読んだ後、私もその答えには何か違和感があると感じましたが、実際にはそうでした。上記の回答には、どこで、そしてなぜ使用するのかについて明確な説明がありません。 $rootScope.$digest
. 。そこで、私が思いついたのがこれです。
まず、なぜですか?使用する必要があります $rootScope.$digest
非角度イベントまたはコールバックから応答するときはいつでも。これには、純粋な DOM イベント、jQuery イベント、およびその他のサードパーティの Promise ライブラリが含まれます。 $q
これは角度の一部です。
第二にどこですか?テストではなくコード内で。注射する必要はありません $rootScope
テストに組み込む場合、実際の Angular サービスでのみ必要になります。ここで、上記のすべてが答えを明確にできていないことがわかります。 $rootScope.$digest
テストから呼び出されたものとして。
これが、次に同じ問題を抱えている人に役立つことを願っています。
アップデート
昨日、この投稿が否決されたため、削除しました。今日、私は上で親切に提供された答えを使用しようとしてこの問題が引き続き発生しました。したがって、私は評判ポイントを犠牲にして自分の回答を保留し、そのため削除を取り消します。
これは非 Angular のイベント ハンドラーで必要なものであり、$q を使用して Jasmine でテストしようとしています。
something.on('ready', function(err) {
$rootScope.$apply(function(){deferred.resolve()});
});
場合によっては $timeout でラップする必要があることに注意してください。
something.on('ready', function(err) {
$timeout(function(){
$rootScope.$apply(function(){deferred.resolve()});
});
});
もう一つメモ。あなたが呼び出している元の問題の例では
done
間違ったタイミングで。電話する必要がありますdone
の内側then
メソッド (またはcatch
またはfinally
)、約束の後に解決されます。Promise が解決される前に呼び出しているため、it
終了する条項。
角マシンテーションから。
https://docs.angularjs.org/api/ng/service/d / $ Q
it('should simulate promise', inject(function($q, $rootScope) {
var deferred = $q.defer();
var promise = deferred.promise;
var resolvedValue;
promise.then(function(value) { resolvedValue = value; });
expect(resolvedValue).toBeUndefined();
// Simulate resolving of promise
deferred.resolve(123);
// Note that the 'then' function does not get called synchronously.
// This is because we want the promise API to always be async, whether or not
// it got called synchronously or asynchronously.
expect(resolvedValue).toBeUndefined();
// Propagate promise resolution to 'then' functions using $apply().
$rootScope.$apply();
expect(resolvedValue).toEqual(123);
}));
.