我有以下用ng-describe编写的茉莉测试,用karma运行。
(我正在使用ES6-承诺填充PhantomJS)
var myModule = angular.module('MyModule', []);
myModule.service('MyService', [function() {
return {
getItems: function() {
// this will be spied and mocked
}
};
}]);
myModule.controller('MyController', ['$scope', 'MyService',
function($scope, MyService) {
$scope.items = [];
$scope.refreshItems = function() {
MyService.getItems().then(
function ok(items) {
$scope.items = items;
console.log('OK, items.length = ' + items.length);
},
function fail(reason) {
console.error('FAIL')
}).catch(console.error.bind(console));
};
}
]);
ngDescribe({
name: "MyController test",
modules: ['MyModule'],
inject: ['MyService', '$rootScope', '$q'],
controllers: 'MyController',
tests: function(deps) {
function getPromise(val) {
return new Promise(function(resolve, reject) {
resolve(val);
});
}
it('updates $scope.items', function() {
spyOn(deps.MyService, 'getItems').and.returnValue(getPromise([4, 5, 6]));
deps.MyController.refreshItems();
deps.$rootScope.$digest();
expect(deps.MyService.getItems).toHaveBeenCalled();
expect(deps.MyController.items.length).toBe(3);
console.log("END OF TEST");
});
}
});测试将失败,因为承诺被解决得太晚了:
LOG: 'END OF TEST'
PhantomJS 1.9.8 (Windows 7 0.0.0) MyController test updates $scope.items FAILED
Expected 0 to be 3.
at d:/git/myproject/test/controllers/ItmngtControllerTest.js:49
LOG: 'OK, items.length = 3'
PhantomJS 1.9.8 (Windows 7 0.0.0): Executed 37 of 37 (1 FAILED) (0.085 secs / 0.26 secs)经过太长时间的调查,我发现如果我使用$q而不是Promise,它就会工作得很好。
function getPromise(val) {
var deferred = deps.$q.defer();
deferred.resolve(val);
return deferred.promise;
}但是,我想知道为什么会出现这种情况,我可以在测试中更改一些东西,使用Promise而不是$q来通过测试吗?
我在很多地方都读过关于$rootScope.$apply()的文章,但是不管我把它放在哪里,它对我来说还是行不通的。
发布于 2015-12-11 17:46:30
角度$q测试是同步的,这是一个巨大的优势。一旦范围$digest()被调用,就可以预期所有$q承诺链处理程序也会被调用。
另一方面,承诺(包括ES6实现)在设计上是异步的。一旦承诺被解决,它的处理程序将在下一个滴答中被调用。所以愉快的角度测试不再是同步的了:
it('updates $scope.items', function (done) {
...
setTimeout(() => {
expect(deps.MyService.getItems).toHaveBeenCalled();
expect(deps.MyController.items.length).toBe(3);
console.log("END OF TEST");
done();
});
});为了测试的目的,可以对Promise进行模拟,以实现同步,在这种情况下可以使用mock-promises。
还有jasmine-co,它的目的是使ES6生成器和co在茉莉花中的异步测试更容易(实际上也是如此),我不知道它在ng-describe中的性能有多好。
https://stackoverflow.com/questions/34228045
复制相似问题