Функция тайм-аута AngularJS $не выполняется в моих спецификациях Jasmine
Я пытаюсь проверить свой контроллер AngularJS с помощью Jasmine, используя Karma. Но $timeout
, который хорошо работает в реальной жизни, сбрасывает мои тесты.
Контроллер:
var Ctrl = function($scope, $timeout) {
$scope.doStuff = function() {
$timeout(function() {
$scope.stuffDone = true;
}, 250);
};
};
Жасмин он блокирует (где $scope
и контроллер правильно инициализированы):
it('should do stuff', function() {
runs(function() {
$scope.doStuff();
});
waitsFor(function() {
return $scope.stuffDone;
}, 'Stuff should be done', 750);
runs(function() {
expect($scope.stuffDone).toBeTruthy();
});
});
Когда я запустил приложение в браузере, будет выполняться функция $timeout
и $scope.stuffDone
будет true. Но в моих тестах $timeout
ничего не делает, функция никогда не выполняется, и Jasmine сообщает об ошибке после выключения 750 мс. Что здесь может быть неправильно?
Ответы
Ответ 1
В соответствии с документацией Angular JS для $timeout вы можете использовать $timeout.flush()
для синхронного сброса очереди отложенных функций.
Попробуйте обновить свой тест:
it('should do stuff', function() {
expect($scope.stuffDone).toBeFalsy();
$scope.doStuff();
expect($scope.stuffDone).toBeFalsy();
$timeout.flush();
expect($scope.stuffDone).toBeTruthy();
});
Вот plunker, показывающий как исходный тест, так и новый тест.
Ответ 2
Как отмечено в одном из комментариев, Jasmine setTimeout
mock не используется, потому что вместо этого используется служба angular JS mock $timeout
. Лично я предпочел бы использовать Jasmine, потому что его издевательский метод позволяет мне проверять длину таймаута. Вы можете эффективно обойти его простым провайдером в unit test:
module(function($provide) {
$provide.constant('$timeout', setTimeout);
});
Примечание: если вы идете по этому маршруту, обязательно вызовите $scope.apply()
после jasmine.Clock.tick.
Ответ 3
Поскольку $timeout
является просто оберткой для window.setTimeout
, вы можете использовать jasmines Clock.useMock()
, который издевается над window.setTimeout
beforeEach(function() {
jasmine.Clock.useMock();
});
it('should do stuff', function() {
$scope.doStuff();
jasmine.Clock.tick(251);
expect($scope.stuffDone).toBeTruthy();
});