我们最近开始在我们的控制器中加入promises以同时处理多个请求,并且它可以在应用程序中运行,但是单元测试这些已被证明是非常困难的,我将很难抓住它的确切内容我很想念以下是两个片段,它们非常简化我正在尝试测试的内容。
控制器:
angular.module('testengine').controller('testController', [
'$scope',
'$q',
'Api',
function($scope, $q, Api) {
$scope.getTest = function (deferred) {
// do stuff...
Api.test.get(params, function(response) {
// do stuff with response
if (deferred) {
deferred.resolve(); // if success
}
});
};
$scope.runTest = function () {
// do stuff...
var promises = [];
var deferred = $q.defer();
promises.push(deferred.promise);
$scope.getTest(deferred);
$q.all(promises).then(function () {
$scope.navigate();
}, function () {
// do stuff with rejected
});
};
$scope.navigate = function () {
// do stuff
};
}]);
测试:
describe('Controller:', function () {
var root, scope, controllerFactory, $q;
function createController () {
return controllerFactory('testController', {
$scope: scope
});
}
beforeEach(function () {
module('testengine');
});
beforeEach(inject(function ($rootScope, $controller, _$q_) {
root = $rootScope;
scope = $rootScope.new();
controllerFactory = $controller;
$q = _$q_;
});
it('should run test', function () {
createController();
var deferred = $q.defer();
spyOn(scope, 'getTest').andReturn(deferred.resolve());
spyOn(scope, 'navigate');
$scope.runTest();
root.$apply();
expect(scope.navigate).toHaveBeenCalled();
});
});
根据所有示例和文档,我已经阅读了promises和$ q,这应该有效,但它没有,而是我得到:
Expected spy navigate to have been called but it was never called.
我猜是因为它与我在嘲笑的间谍中解决的延迟对象不一样,但我怎么想嘲笑那个?我是否必须在控制器或范围上绑定延迟对象或什么?
您看到的结构的原因是因为使用getTest()有不同的方法(有些不仅使用该请求而且还使用其他请求,因此承诺)。此外,getTest()在另一个测试中单独测试,这就是为什么我想要模拟该函数及其中的任何请求。
任何帮助都表示赞赏,如果我犯了一些明显的错误,我很高兴教育自己仍然是Angular的新手。
答案 0 :(得分:1)
是的,你没有解决正确的承诺。您需要拦截函数参数。
spyOn(scope, 'getTest');
expect(scope.getTest).toHaveBeenCalled();
scope.getTest.mostRecentCall.args[0].resolve();
这是一个很简洁的Jasmine参考:http://tobyho.com/2011/12/15/jasmine-spy-cheatsheet/