我正在尝试测试使用服务的控制器。当我在inject函数中运行以下测试和断点时,将注入实际服务而不是模拟服务。为什么通过$ provider.factory定义的服务没有被注入?
"use strict";
describe("contestantController", function () {
var dataService, rootScope, scope, passPromise, contestantController;
beforeEach(function(){
module(function ($provide) {
//mock service
$provide.factory('contestantDataService', ['$q', function ($q) {
function save(data){
if(passPromise){
return $q.when();
} else {
return $q.reject();
}
}
function getData() {
if (passPromise) {
return $q.when(smallDataSet());
} else {
return $q.reject();
}
}
return {
addContestant: save,
getContestants: getData,
};
}]);
});
module('contestantApp');
});
beforeEach(inject(function ($rootScope, $controller, contestantDataService) {
rootScope = $rootScope;
scope = $rootScope.$new();
dataService = contestantDataService;
spyOn(dataService, 'getContestants').and.callThrough();
contestantController = $controller('contestantController', {
$scope: scope,
contestantDataService: dataService
});
}));
it('should call getContestants method on contestantDataService on calling saveData', function () {
passPromise = true;
rootScope.$digest();
expect(dataService.getContestants).toHaveBeenCalled();
expect(scope.contestants).toEqual(smallDataSet());
});
});
答案 0 :(得分:3)
module()
函数只是注册inject()
函数稍后用于初始化Angular注入器的模块或模块初始化函数。它绝不会将模拟服务与模块链接起来。
您的代码不起作用,因为服务注册的顺序很重要。您的代码首先注册一个模拟contestantDataService
,然后注册contestantApp
模块,该模块包含自己的contestantDataService
,覆盖已注册的模拟。如果您只是将module('contestantApp')
调用移到顶部,它应该按预期工作。
所以这意味着下面的两个方块是等效的,并且都可以工作......
beforeEach(function(){
module('contestantApp');
module(function ($provide) {
...
});
);
和
beforeEach(function(){
module('contestantApp', function ($provide) {
...
});
);
答案 1 :(得分:2)
@Yunchi的Thx。你指出了我的错误。
在模拟服务contestantDataService
之前,您应该调用模块函数。
只需以这种方式更新您的代码,
//make sure contesttantDataService exist in this module in your production environment.
var dataService, rootScope, scope, passPromise, contestantController;
beforeEach(function(){
//Add module name here which means we define the mockService under this module
module('contestantApp', function ($provide) {
//mock service
$provide.factory('contestantDataService', ['$q', function ($q) {
function save(data){
if(passPromise){
return $q.when();
} else {
return $q.reject();
}
}
function getData() {
if (passPromise) {
return $q.when(smallDataSet());
} else {
return $q.reject();
}
}
return {
addContestant: save,
getContestants: getData,
};
}]);
});
beforeEach(inject(function ($rootScope, $controller, contestantDataService) {
rootScope = $rootScope;
scope = $rootScope.$new();
dataService = contestantDataService;
spyOn(dataService, 'getContestants').and.callThrough();
//no need to manually inject to our controller now.
contestantController = $controller('contestantController', {
$scope: scope
});
}));
我认为最好在我们的单元测试中使用$provide.factory
,而不是使用$provide.value
。因为我们只需要确保contestantDataService
是一个对象并具有该功能。
以下是您可以查看的类似问题,
Injecting a mock into an AngularJS service.
Mock a service in order to test a controller.
Here is the jsfiddle I just created.
玩得开心。 :)