約束 $scope.$digest()
を強制しない限り、Angular/Jasmineテストで解決しないでください 。これは馬鹿げたIMOですが、問題ありません(該当する場合)(コントローラー)。
私が今いる状況は、アプリケーション内のスコープをあまり気にしないサービスがあり、サーバーからデータを返すだけですが、約束は解決していないようです。
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の挿入とダイジェストを強制されているようです。
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();
angularドキュメントから。
https://docs.angularjs.org/api/ng/service/ $ 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);
}));
だから私は午後ずっとこれに苦労しています。この投稿を読んだ後、私も答えに何か外れていると感じました。上記の回答では、$rootScope.$digest
を使用する場所と理由について明確な説明がありません。だから、ここに私が思いついたものがあります。
なぜ最初に?角度のないイベントまたはコールバックから応答するときは常に$rootScope.$digest
を使用する必要があります。これには、純粋なDOMイベント、jQueryイベント、および角度の一部である$q
以外のサードパーティのPromiseライブラリが含まれます。
第二にどこに?テストではなく、コードで。テストに$rootScope
を挿入する必要はありません。実際のangularサービスでのみ必要です。上記のすべてが答えが何であるかを明確にできない場合、それらは、テストから呼び出されたものとして$rootScope.$digest
を示します。
これが、同じ問題である次の人に役立つことを願っています。
昨日、この投稿が投票されたときに削除しました。今日、私はこの問題に答えを使用しようとし続けました。したがって、評判ポイントを犠牲にして回答を待機します。そのため、削除を取り消しています。
これは、非角度のイベントハンドラーで必要なものであり、$ 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()});
});
});
もう1つ注意してください。元の問題の例では、
done
を間違ったタイミングで呼び出しています。解決後、promiseのdone
メソッド(またはthen
またはcatch
)内でfinally
を呼び出す必要があります。 promiseが解決する前に呼び出しているため、it
句が終了します。