Таким образом, у меня есть контроллер, как это:Как проверить angularjs поведения асинхронного контроллера без использования тайма-аута
angular.module('someModule').controller('someController',function(productService) {
$scope.products = [];
$scope.init = function() {
aService.fetchAll().then(function(payload) {
$scope.products = filterProducts(payload.data);
});
}
$scope.init();
function filterProducts(products) {
//for each of products filter some specific ones
return filteredProducts;
}
});
Я пишу тест, который будет вызывать $ scope.init() и должен убедиться, что продукты фильтруют соответствующим образом. Я насмешливый $ httpBackend поэтому код выглядит следующим образом:
describe("someController", function() {
"use strict";
var $controller; //factory
var controller; //controller
var $rootScope;
var $state;
var $stateParams;
var $injector;
var $scope;
var $httpBackend;
var productService;
beforeEach(function(){
angular.mock.module("someModule")
inject(function (_$rootScope_, _$state_, _$injector_, $templateCache, _$controller_, _$stateParams_, _$httpBackend_, _productService_) {
$rootScope = _$rootScope_;
$state = _$state_;
$stateParams = _$stateParams_;
$injector = _$injector_;
$controller = _$controller_;
$httpBackend = _$httpBackend_;
productService = _productService_;
});
controller = $controller("someController", {$scope: $scope, $state: $state});
});
it("init() should filter products correctly",function(){
//Arrange
var expectedFilteredProducts = ["1","2"];
var products = ["0","1","2"];
$httpBackend.whenGET("api/products").respond(products);
//Act
$scope.init();
//Assert
setTimeout(100,function(){
expect($scope.products).toEqual(expectedFilteredProducts);
});
$httpBackend.flush();
});
});
Проблема заключается в том, что без SetTimeout тест не проходит. Есть ли способ проверить, что я пытаюсь сделать без него, и не вводя сложные $ q/обещания только для теста? В качестве дополнительной заметки productService возвращает обещание $ http. Благодарю.
Edit: SetTimeout делает пробный запуск, но не утверждения не происходит ..
Если '$ scope.init()' вернул обещание, это было бы намного проще. (и для этого требуется только добавить 7 символов) –
Я считаю, что это '$ httpBackend.flush()', что вы хотите; выполните его после раздела '// Act', и ожидание будет работать без таймаута. Также обратите внимание, что контроллер * уже вызвал * 'scope.init()', поэтому вам не нужно вызывать его снова в тесте. –
@NikosParaskevopoulos, который исправил это! Также с помощью setTimeout тест выполнялся, но ничего не утверждал. Вы можете отправить более подробный ответ, и я его приму. В моем исходном коде у меня было $ httpBackend.flush() после действия. Теперь я воссоздаю контроллер и вызываю init только для этого теста. Спасибо –