为什么$只在'angular.mock.module'函数中可用,$ q只在'angular.mock.inject'函数中可用?
我正在嘲笑一个AngularJSunit testing的服务。 我正在使用$provide
服务来replace模拟出来的“真实”服务(这是一个可用的plunker脚本 ):
describe('My Controller', function () { var $scope; var $provide; beforeEach(angular.mock.module('myApp')); beforeEach(angular.mock.module(function (_$provide_) { $provide = _$provide_; })); beforeEach(angular.mock.inject(function($rootScope, $controller, $q){ var mockMyService = { getAll : function() { var deferred = $q.defer(); deferred.resolve([ { itemText: "Foo" }, { itemText: "Bar" } ]); return deferred.promise; } }; $provide.value('myService', mockMyService); $scope = $rootScope.$new(); $controller('MyCtrl', { $scope: $scope }); $rootScope.$apply(); })); it('Has two items defined', function () { expect($scope.items.length).toEqual(2); }); });
这工作得很好。 但是,我不喜欢我使用angular.mock.module
函数只是为了引用$provide
服务,然后在下面的angular.mock.inject
函数中使用。 但是,如果直接将$provide
作为参数添加到angular.mock.inject
函数中,则会出现“未知提供者”错误。
我发现我可以把所有的angular.mock.module
代码放在angular.mock.module
函数中。 但是,我也有类似的问题与$q
参考,我需要嘲笑的服务必须返回一个承诺。
换句话说,如果我添加一个$q
参数给angular.mock.module
函数,那么我也会得到一个“unknown provider”错误。
有没有办法简化这个? 很明显,我有作品,但不知何故,感觉不太对。 我觉得我不了解为什么有些提供程序可用于inject
function,而其他提供module
function。
inject
函数中不能使用$provide
,因为前者为后者提供注册提供者。 看一看:
describe('...', function() { beforeEach(function() { module(function($provide) { $provide.constant('someValue', 'foobar'); }); inject(function(someValue) { var value = someValue; // will be 'foobar'; }); }); });
你可以这样写你的testing:
describe('...', function() { var serviceMock; beforeEach(function() { serviceMock = { someMethod: function() { ... } }; module(function($provide) { $provide.value('service', serviceMock); }); inject(function(service) { ... }); }); });
实际上,在使用$provide
注入之前,您甚至不需要实施模拟服务:
beforeEach(function() { serviceMock = {}; module(function($provide) { $provide.value('service', serviceMock); }); inject(function(service) { ... }); }); it('tests something', function() { // Arrange serviceMock.someMethod = function() { ... } // Act // does something // Assert expect(...).toBe(...); });
这里是一个Plunker脚本主要说明上述。
当我必须包装一个使用$q
的服务并且看起来非常干净时,
var _ServiceToTest_; beforeEach(function () { module('module.being.tested'); module(function ($provide) { $provide.factory('ServiceToMock', function ($q, $rootScope) { var service = ...; // use $q et al to heart's content return service; }); }); inject(function (_ServiceToTest_) { ServiceToTest = _ServiceToTest_; }); }); it('...', function () { /* code using ServiceToTest */ });
诀窍是使用$provide.factory
而不是$provide.value
。