Javascript 使用Jasmine spyOn和工厂中定义的对象方法
在我的angular JS应用程序中,我有一个mainController,它接受userFactory作为参数。 userFactory由一个名为userService的对象组成,该对象又有一个userDetails对象和一些方法,包括resetUserDetails。(见下文) 在主控制器中,我有一个注销函数,它调用Javascript 使用Jasmine spyOn和工厂中定义的对象方法,javascript,angularjs,jasmine,spyon,Javascript,Angularjs,Jasmine,Spyon,在我的angular JS应用程序中,我有一个mainController,它接受userFactory作为参数。 userFactory由一个名为userService的对象组成,该对象又有一个userDetails对象和一些方法,包括resetUserDetails。(见下文) 在主控制器中,我有一个注销函数,它调用userFactory.userService.resetUserDetails方法。我想用jasmine测试这个注销功能,但是我得到了一些错误。我对茉莉花很陌生,所以如果我错过
userFactory.userService.resetUserDetails
方法。我想用jasmine测试这个注销功能,但是我得到了一些错误。我对茉莉花很陌生,所以如果我错过了一些明显的东西,我向你道歉
因此,首先在我的Jasmine套件中,我创建了一个MainControllerSpec来测试我的mainController
在这个规范中,我注入了一个名为userFactory的工厂。我试图监视我的resetUserDetails
方法,如下所示,但出现错误:
spyOn(userFactory, 'userService.resetUserDetails');
错误:userService.resetUserDetails()
不存在
我通过在我的userFactory中(在userService对象之外)创建一个名为test的函数来尝试这个过程,它运行良好,因此至少我知道规范中的工厂注入设置良好。非常感谢您的帮助。谢谢 MainControllerSpec.js 主控制器中的注销功能 用户工厂
在直接注入之前,您需要模拟您的
userFactory
。
单元测试的目标是将文件作为黑盒进行测试,而不直接测试相关方法的逻辑
对于它们,您将为userFactory
编写规范文件
在这种情况下,您可以执行以下操作:
描述(“主控制器”,函数(){
每个之前(angular.mock.module('mapModule','ngRoute','ngTouch','ngAnimate');
var范围,userFactory;
//这里是你们工厂的方法
每个模块之前(功能($PROFECT){
$provide.value('userFactory'{
myFirstObject:{
myFirstMethod:函数(){}
}
});
}));
beforeach(注入(函数($rootScope、$controller、\u userFactory){
scope=$rootScope.$new();
userFactory=\u userFactory;
$controller('mainController'{
$scope:scope
});
}));
描述('注销函数',函数(){
它('应调用userFactory.userService对象的resetUserDetails函数并重置userDetails对象',函数(){
//这里监视方法并返回您希望在此测试中返回的内容
//或者,如果您不需要管理退货,就像您看起来不需要的那样,只需使用callThrough
spyOn(userFactory.myFirstObject,'myFirstMethod')。和.callThrough();
scope.logOut();
expect(userFactory.myFirstObject.myFirstMethod).toHaveBeenCalled();
});
});
});代码>我刚抓到它。道歉。下面的操作很好。spyOn(userFactory.userService,'resetUserDetails')。。通常,您可能希望在控制器测试中完全模拟服务,而不是逐个监视其方法。好的,谢谢你的建议。我查一下out@estus谢谢,在我的例子中,我会这样做来监视工厂(在全局范围内):beforeach(function(){module('mapModule',{userFactory:{userService:jasmine.createSpy()});});然后在套件中:descripe('注销函数',函数(){…我应该省去spyOn行吗?我试过了,但没用。谢谢你的帮助。我是jasmineuserService的新手,不应该是间谍。它是一个包含resetUserDetails
方法的对象。你的情况与链接答案中的情况完全相同。如果函数已经是间谍,则不需要spyOn。相反,间谍返回的值应该是be设置为和.returnValue(…)
(如果需要)。谢谢。我明天会尝试。虽然我修复了我自己的代码,正如您在上面的评论中所看到的。我需要这样说:spyOn(userFactory.userService,'resetUserDetails');而不是:spyOn(userFactory,'userService.resetUserDetails')。。(因为我的方法在userFactory中的一个名为userService的对象中)…但是我很感谢你的建议,并将尝试你的建议。谢谢抱歉没有注意到你的方法在嵌套对象中,在回答中更改了代码谢谢。我试过了,并且工作得很好。谢谢。不过我做了一件额外的事情(感谢评论中的另一个人)。我使用jasmine.createSpy()so$provide.value('userFactory',{myFirstObject:{myFirstMethod:jasmine.createSpy()}}创建了一个间谍;然后我不需要在套件中的测试中使用spyOn,而是继续使用其余的代码。无论如何,你的答案对我的问题是正确的,所以我现在就接受它。非常感谢你。这是绝对有效的。通过这种方式,你可以直接在那里做间谍,但是如果在将来的测试中,你需要间谍只是在某个测试中,在你之前需要模拟函数,您需要正常启动定义,然后spyOn
describe("MainController", function () {
beforeEach(angular.mock.module('mapModule', 'ngRoute','ngTouch', 'ngAnimate'));
var scope, userFactory;
beforeEach(inject(function($rootScope, $controller, _userFactory_){
scope = $rootScope.$new();
userFactory = _userFactory_;
$controller('mainController', {
$scope: scope
});
}));
describe('The logOut function', function() {
it('should call the resetUserDetails function of the userFactory.userService object and reset the userDetails object', function() {
//spyOn takes in a factory and a method of that factory
spyOn(userFactory, 'userService.resetUserDetails');
//spyOn(userFactory, 'test'); tried this and it works.
scope.logOut();
expect(userFactory.userService.resetUserDetails).toHaveBeenCalled();
});
});
});
$scope.logOut = function(){
userFactory.userService.resetUserDetails();
//userFactory.test(); //tried this with spyOn in jasmine
}
mapApp.factory('userFactory', function(){
var userService = {
/*
* Initialize a userDetails object.
*/
userDetails : {
"userID" : null,
"facebookUserID" : "",
"facebookName" : "",
"facebookProfilePic" : "",
"userPrivilegeID" : 1,
"userToken" : "",
"isLoggedIn" : false
},
resetUserDetails : function(){
/*
* This method resets the userDetails object.
*/
this.userDetails = {
"userID" : null,
"facebookUserID" : "",
"facebookName" : "",
"facebookProfilePic" : "",
"userPrivilegeID" : 1,
"userToken" : "",
"isLoggedIn" : false
};
}
};
var test = function(){
/*
* for testing spyOn in Jasmine
*/
};
//return public API so that we can access it in all controllers
return{
userService: userService,
test: test
};
});