我正在为一个AngularJS单元测试嘲笑一个服务。我使用$ provide服务来替换’真正的’服务与模拟的一个(这是一个
plunker script可用):
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函数。但是,我有一个类似的问题与$ q引用,我需要作为我的模拟服务必须返回一个承诺。
换句话说,如果我添加一个$ q参数到angular.mock.module函数,那么我也得到一个’未知的提供者’的错误。
有办法简化这个吗?显然,我有工作,但它不觉得不对,不知何故。我觉得我缺乏理解为什么一些提供程序可用的注入功能和其他可用的模块功能。
你不能在inject函数中使用$ provide,因为前者注册提供者以供后者使用。看一看:
describe('...',function() { beforeEach(function() { module(function($provide) { $provide.constant('someValue','foobar'); }); inject(function(someValue) { var value = someValue; // will be 'foobar'; }); }); });
你可以这样写你的测试:
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 script,说明了上面的大部分。