未注入模拟服务,但正在注入实际服务
Mock service is not being injected but actual service is being injected
我正在尝试测试使用服务的控制器。当我 运行 在注入函数中进行以下测试和断点时,将注入实际服务而不是模拟服务。为什么通过 $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());
});
});
感谢@Yunchi。你指出了我的错误。
您应该在模拟服务之前调用模块函数 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.value
比使用 $provide.factory
更好。因为我们只需要确保 contestantDataService
是一个对象并具有功能即可。
您可以查看以下类似问题,
Injecting a mock into an AngularJS service.
Mock a service in order to test a controller.
Here is the jsfiddle I just created.
玩得开心。 :)
Tyler 的回答可以,但推理有点不对。
module()
函数简单地注册模块或模块初始化函数,inject()
函数稍后将使用这些模块或模块初始化函数来初始化 Angular 注入器。它决不会将模拟服务与模块链接起来。
您的代码不起作用,因为注册服务的顺序很重要。您的代码首先注册一个 mock contestantDataService
,然后注册 contestantApp
模块,其中包含自己的 contestantDataService
,覆盖已注册的 mock。如果您只是将 module('contestantApp')
调用移动到顶部,它应该会按预期工作。
所以这意味着下面的两个块是等效的并且都可以工作...
beforeEach(function(){
module('contestantApp');
module(function ($provide) {
...
});
);
和
beforeEach(function(){
module('contestantApp', function ($provide) {
...
});
);
我正在尝试测试使用服务的控制器。当我 运行 在注入函数中进行以下测试和断点时,将注入实际服务而不是模拟服务。为什么通过 $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());
});
});
感谢@Yunchi。你指出了我的错误。
您应该在模拟服务之前调用模块函数 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.value
比使用 $provide.factory
更好。因为我们只需要确保 contestantDataService
是一个对象并具有功能即可。
您可以查看以下类似问题,
Injecting a mock into an AngularJS service.
Mock a service in order to test a controller.
Here is the jsfiddle I just created.
玩得开心。 :)
Tyler 的回答可以,但推理有点不对。
module()
函数简单地注册模块或模块初始化函数,inject()
函数稍后将使用这些模块或模块初始化函数来初始化 Angular 注入器。它决不会将模拟服务与模块链接起来。
您的代码不起作用,因为注册服务的顺序很重要。您的代码首先注册一个 mock contestantDataService
,然后注册 contestantApp
模块,其中包含自己的 contestantDataService
,覆盖已注册的 mock。如果您只是将 module('contestantApp')
调用移动到顶部,它应该会按预期工作。
所以这意味着下面的两个块是等效的并且都可以工作...
beforeEach(function(){
module('contestantApp');
module(function ($provide) {
...
});
);
和
beforeEach(function(){
module('contestantApp', function ($provide) {
...
});
);