J'ai une fonction dans l'un de mes services angular que j'aimerais être appelé à plusieurs reprises à intervalles réguliers. J'aimerais le faire en utilisant $ timeout. Cela ressemble à ceci:
var interval = 1000; // Or something
var _tick = function () {
$timeout(function () {
doStuff();
_tick();
}, interval);
};
_tick();
Je suis perplexe sur la façon de tester cela avec Jasmine en ce moment - Comment dois-je faire? Si j'utilise $timeout.flush()
alors les appels de fonction se produisent indéfiniment. Si j'utilise l'horloge factice de Jasmine, $timeout
Ne semble pas être affecté. Fondamentalement, si je peux faire fonctionner cela, je devrais être prêt à partir:
describe("ANGULAR Manually ticking the Jasmine Mock Clock", function() {
var timerCallback, $timeout;
beforeEach(inject(function($injector) {
$timeout = $injector.get('$timeout');
timerCallback = jasmine.createSpy('timerCallback');
jasmine.Clock.useMock();
}));
it("causes a timeout to be called synchronously", function() {
$timeout(function() {
timerCallback();
}, 100);
expect(timerCallback).not.toHaveBeenCalled();
jasmine.Clock.tick(101);
expect(timerCallback).toHaveBeenCalled();
});
});
Ces deux variantes fonctionnent, mais ne m'aident pas:
describe("Manually ticking the Jasmine Mock Clock", function() {
var timerCallback;
beforeEach(function() {
timerCallback = jasmine.createSpy('timerCallback');
jasmine.Clock.useMock();
});
it("causes a timeout to be called synchronously", function() {
setTimeout(function() {
timerCallback();
}, 100);
expect(timerCallback).not.toHaveBeenCalled();
jasmine.Clock.tick(101);
expect(timerCallback).toHaveBeenCalled();
});
});
describe("ANGULAR Manually flushing $timeout", function() {
var timerCallback, $timeout;
beforeEach(inject(function($injector) {
$timeout = $injector.get('$timeout');
timerCallback = jasmine.createSpy('timerCallback');
}));
it("causes a timeout to be called synchronously", function() {
$timeout(function() {
timerCallback();
}, 100);
expect(timerCallback).not.toHaveBeenCalled();
$timeout.flush();
expect(timerCallback).toHaveBeenCalled();
});
});
Merci d'avance!
Ne faites pas votre test Async en utilisant l'horloge de Jasmine. À la place, utilisez $timeout.flush()
pour maintenir de manière synchrone le flux du test. Cela peut être un peu difficile à configurer, mais une fois que vous l'avez obtenu, vos tests seront plus rapides et plus contrôlés.
Voici un exemple de test qui le fait en utilisant cette approche: https://github.com/angular/angular.js/blob/master/test/ngAnimate/animateSpec.js#L618
La réponse de @ matsko m'a conduit sur la bonne voie. J'ai pensé publier ma solution "complète" pour trouver plus facilement la réponse.
angular.module("app").service("MyService", function() {
return {
methodThatHasTimeoutAndReturnsAPromise: function($q, $timeout) {
var deferred = $q.defer();
$timeout(function() {
deferred.resolve(5);
}, 2000);
return deferred.promise;
}
};
});
describe("MyService", function() {
var target,
$timeout;
beforeEach(inject(function(_$timeout_, MyService) {
$timeout = _$timeout_;
target = MyService;
}));
beforeEach(function(done) {
done();
});
it("equals 5", function(done) {
target.methodThatHasTimeoutAndReturnsAPromise().then(function(value) {
expect(value).toBe(5);
done();
});
$timeout.flush();
});
});