将 Jasmine spyOn 与工厂中定义的对象的方法一起使用
Using Jasmine spyOn with a method of an object defined in a factory
在我的 angular JS 应用程序中,我有一个 mainController,它将 userFactory 作为参数。
userFactory 由一个名为 userService 的对象组成,该对象又具有一个 userDetails 对象和一些方法,包括 resetUserDetails。 (往下看)
在 mainController 中,我有一个调用 userFactory.userService.resetUserDetails
方法的 logOut 函数。我想用 jasmine 测试这个 logOut 函数,但是我遇到了一些错误。我是 Jasmine 的新手,如果我遗漏了一些明显的东西,我深表歉意。
所以首先在我的 Jasmine 套件中我创建了一个 MainControllerSpec 来测试我的 mainController。
在此规范中,我正在注入一个名为 userFactory 的工厂。我正在尝试按如下方式监视我的 resetUserDetails
方法,但出现错误:
spyOn(userFactory, 'userService.resetUserDetails');
错误:userService.resetUserDetails()
不存在。
我通过在我的 userFactory(在 userService 对象之外)中创建一个名为 test 的函数来尝试这个过程,它运行良好,所以至少我知道规范中的工厂注入设置得很好。
非常感谢任何帮助。谢谢
MainControllerSpec.js
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();
});
});
});
mainController 中的 logOut 函数
$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
};
});
您需要先模拟 userFactory
才能直接注入。
单元测试的目标是将文件作为黑盒进行测试,而不直接测试相关方法的逻辑。
对于他们,您将为 userFactory
编写规范文件。
在这种情况下,您可以执行以下操作:
describe("MainController", function() {
beforeEach(angular.mock.module('mapModule', 'ngRoute', 'ngTouch', 'ngAnimate'));
var scope, userFactory;
// here mock the methods of your factory
beforeEach(module(function($provide) {
$provide.value('userFactory', {
myFirstObject: {
myFirstMethod: function() {}
}
});
}));
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() {
//here spy on the method and return what you would like to return in this test
// or if you don't need to manage the return, as it seems you don't, just use callThrough
spyOn(userFactory.myFirstObject, 'myFirstMethod').and.callThrough();
scope.logOut();
expect(userFactory.myFirstObject.myFirstMethod).toHaveBeenCalled();
});
});
});
在我的 angular JS 应用程序中,我有一个 mainController,它将 userFactory 作为参数。 userFactory 由一个名为 userService 的对象组成,该对象又具有一个 userDetails 对象和一些方法,包括 resetUserDetails。 (往下看)
在 mainController 中,我有一个调用 userFactory.userService.resetUserDetails
方法的 logOut 函数。我想用 jasmine 测试这个 logOut 函数,但是我遇到了一些错误。我是 Jasmine 的新手,如果我遗漏了一些明显的东西,我深表歉意。
所以首先在我的 Jasmine 套件中我创建了一个 MainControllerSpec 来测试我的 mainController。
在此规范中,我正在注入一个名为 userFactory 的工厂。我正在尝试按如下方式监视我的 resetUserDetails
方法,但出现错误:
spyOn(userFactory, 'userService.resetUserDetails');
错误:userService.resetUserDetails()
不存在。
我通过在我的 userFactory(在 userService 对象之外)中创建一个名为 test 的函数来尝试这个过程,它运行良好,所以至少我知道规范中的工厂注入设置得很好。
非常感谢任何帮助。谢谢
MainControllerSpec.js
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();
});
});
});
mainController 中的 logOut 函数
$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
};
});
您需要先模拟 userFactory
才能直接注入。
单元测试的目标是将文件作为黑盒进行测试,而不直接测试相关方法的逻辑。
对于他们,您将为 userFactory
编写规范文件。
在这种情况下,您可以执行以下操作:
describe("MainController", function() {
beforeEach(angular.mock.module('mapModule', 'ngRoute', 'ngTouch', 'ngAnimate'));
var scope, userFactory;
// here mock the methods of your factory
beforeEach(module(function($provide) {
$provide.value('userFactory', {
myFirstObject: {
myFirstMethod: function() {}
}
});
}));
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() {
//here spy on the method and return what you would like to return in this test
// or if you don't need to manage the return, as it seems you don't, just use callThrough
spyOn(userFactory.myFirstObject, 'myFirstMethod').and.callThrough();
scope.logOut();
expect(userFactory.myFirstObject.myFirstMethod).toHaveBeenCalled();
});
});
});