如何在茉莉花单元测试中模拟 $state.params
how to mock $state.params in jasmine unit testing
我有以下控制器EditMeetingCtrl.js
(function() {
'use strict';
angular
.module('myApp')
.controller('EditMeetingCtrl', EditMeetingCtrl);
EditMeetingCtrl.$inject = ['$rootScope', '$scope', '$state', '$http', '$translate',
'meetingService', 'companyService', 'notificationService', 'meeting'];
function EditMeetingCtrl($rootScope, $scope, $state, $http, $translate, meetingService, companyService, notificationService, meeting) {
$scope.meeting = meeting;
$scope.companyId = $state.params.companyId;
$scope.save = save;
function save() {
$scope.buttonDisable = true;
meetingService.saveMeeting($state.params.companyId, $state.params.meetingId, $scope.meeting)
.success(function(meetingId) {
//more code
});
}
}
})();
EditMeetingCtrlSpec.js 测试用例
describe('in EditMeetingCtrl', function () {
var companyService , meetingService ;
meetingId = 123321 ;
companyId = 456654 ;
meetingObj = {} ;
var fakeHttpPromise = {
success: function() {}
};
beforeEach(angular.mock.module('myApp'));
beforeEach(angular.mock.inject(function (_$httpBackend_, _companyService_ , _meetingService_) {
$httpBackend = _$httpBackend_;
companyService = _companyService_;
meetingService = _meetingService_ ;
}));
describe('EditMeetingCtrl.save()', function () {
var $rootScope, scope, $controller , $q ;
beforeEach(inject(function ($rootScope, $controller , _meetingService_ ) {
scope = $rootScope.$new();
createController = function() {
return $controller('EditMeetingCtrl', {
$scope: scope,
meeting : {} ,
meetingService : _meetingService_
});
};
var controller = new createController();
}));
it("should save the meeting object", function() {
spyOn(meetingService, 'saveMeeting').and.returnValue(fakeHttpPromise);
scope.save();
expect(meetingService.saveMeeting).toHaveBeenCalledWith( meetingId , companyId , meetingObj);
});
});
});
当尝试 运行 下面的测试用例时 EditMeetingCtrlSpec.js 我遇到了以下测试失败
PhantomJS 1.9.8 (Windows 8) EditMeetingCtrl Spying --> EditMeetingCtrl.save() should save the meeting FAILED
Expected spy saveMeeting to have been called with [ 123321, 456654, Object({ }) ] but actual calls were [ undef
ined, undefined, Object({ }) ].
所以理解我这个问题的方法是,save()
方法的服务调用包含 $state.params.companyId, $state.params.meetingId
参数,并且在调用服务调用时发送 undefined
值。因此我需要模拟 $state.params
。不知道该怎么做。有人能指出我正确的方向吗?
在 Michael Radionov 回答后进行编辑
describe('EditMeetingCtrl.save()', function () {
var $rootScope, scope, $controller , $q , $state ;
beforeEach(inject(function ($rootScope, $controller , $state , _meetingService_ ) {
scope = $rootScope.$new();
createController = function() {
return $controller('EditMeetingCtrl', {
$scope: scope,
meeting : {} ,
meetingService : _meetingService_
});
};
var controller = new createController();
}));
it("should save the meeting", function() {
$state.params = { companyId: 123, meetingId: 567 };
spyOn(meetingService, 'saveMeeting').and.returnValue(fakeHttpPromise);
scope.save();
//expect(meetingService.saveMeeting).toHaveBeenCalledWith( meetingId , companyId , meetingObj);
});
});
我已经完成了上面的操作,但是我收到以下错误消息,提示 $state is not defined 。
Firefox 38.0.0 (Windows 8.1) In EditMeetingCtrl EditMeetingCtrl.save() should save the meeting FAILED
TypeError: $state is undefined in C:/Users/sal/Documents/myApp/test/meeting/EditMe
etingCtrlSpec.js (line 80)
我假设这是因为我没有在注入方法中这样做 -> $state : state
,所以我也尝试这样做但得到了同样的错误。我在这里错过了什么?
您可以模拟整个 $state
提供程序,然后在调用 save
:[=14 之前在 params
属性 中准确指定您想要的值=]
describe('in EditMeetingCtrl', function () {
// ...
beforeEach(angular.mock.module('myApp'));
beforeEach(angular.mock.module(function ($provide) {
// mock the entire $state provider
$provide.provider('$state', function () {
return {
$get: function () {
return {
// by default it will be an empty object
params: {}
};
}
};
});
}));
// ....
describe('EditMeetingCtrl.save()', function () {
// inject mocked $state - one that you've provided above
var $rootScope, scope, $controller, $q, state;
// ---------------------------------------^^^
beforeEach(inject(function ($rootScope, $controller, $state, _meetingService) {
// ------------------------------------------------^^^
state = $state;
}));
// ...
it("should save the meeting object", function() {
// provide custom params which will be used in a call
state.params = { companyId: 123, meetingId: 567 };
spyOn(meetingService, 'saveMeeting').and.returnValue(fakeHttpPromise);
scope.save();
expect(meetingService.saveMeeting).toHaveBeenCalledWith( meetingId , companyId , meetingObj);
});
});
// ...
});
我有以下控制器EditMeetingCtrl.js
(function() {
'use strict';
angular
.module('myApp')
.controller('EditMeetingCtrl', EditMeetingCtrl);
EditMeetingCtrl.$inject = ['$rootScope', '$scope', '$state', '$http', '$translate',
'meetingService', 'companyService', 'notificationService', 'meeting'];
function EditMeetingCtrl($rootScope, $scope, $state, $http, $translate, meetingService, companyService, notificationService, meeting) {
$scope.meeting = meeting;
$scope.companyId = $state.params.companyId;
$scope.save = save;
function save() {
$scope.buttonDisable = true;
meetingService.saveMeeting($state.params.companyId, $state.params.meetingId, $scope.meeting)
.success(function(meetingId) {
//more code
});
}
}
})();
EditMeetingCtrlSpec.js 测试用例
describe('in EditMeetingCtrl', function () {
var companyService , meetingService ;
meetingId = 123321 ;
companyId = 456654 ;
meetingObj = {} ;
var fakeHttpPromise = {
success: function() {}
};
beforeEach(angular.mock.module('myApp'));
beforeEach(angular.mock.inject(function (_$httpBackend_, _companyService_ , _meetingService_) {
$httpBackend = _$httpBackend_;
companyService = _companyService_;
meetingService = _meetingService_ ;
}));
describe('EditMeetingCtrl.save()', function () {
var $rootScope, scope, $controller , $q ;
beforeEach(inject(function ($rootScope, $controller , _meetingService_ ) {
scope = $rootScope.$new();
createController = function() {
return $controller('EditMeetingCtrl', {
$scope: scope,
meeting : {} ,
meetingService : _meetingService_
});
};
var controller = new createController();
}));
it("should save the meeting object", function() {
spyOn(meetingService, 'saveMeeting').and.returnValue(fakeHttpPromise);
scope.save();
expect(meetingService.saveMeeting).toHaveBeenCalledWith( meetingId , companyId , meetingObj);
});
});
});
当尝试 运行 下面的测试用例时 EditMeetingCtrlSpec.js 我遇到了以下测试失败
PhantomJS 1.9.8 (Windows 8) EditMeetingCtrl Spying --> EditMeetingCtrl.save() should save the meeting FAILED
Expected spy saveMeeting to have been called with [ 123321, 456654, Object({ }) ] but actual calls were [ undef
ined, undefined, Object({ }) ].
所以理解我这个问题的方法是,save()
方法的服务调用包含 $state.params.companyId, $state.params.meetingId
参数,并且在调用服务调用时发送 undefined
值。因此我需要模拟 $state.params
。不知道该怎么做。有人能指出我正确的方向吗?
在 Michael Radionov 回答后进行编辑
describe('EditMeetingCtrl.save()', function () {
var $rootScope, scope, $controller , $q , $state ;
beforeEach(inject(function ($rootScope, $controller , $state , _meetingService_ ) {
scope = $rootScope.$new();
createController = function() {
return $controller('EditMeetingCtrl', {
$scope: scope,
meeting : {} ,
meetingService : _meetingService_
});
};
var controller = new createController();
}));
it("should save the meeting", function() {
$state.params = { companyId: 123, meetingId: 567 };
spyOn(meetingService, 'saveMeeting').and.returnValue(fakeHttpPromise);
scope.save();
//expect(meetingService.saveMeeting).toHaveBeenCalledWith( meetingId , companyId , meetingObj);
});
});
我已经完成了上面的操作,但是我收到以下错误消息,提示 $state is not defined 。
Firefox 38.0.0 (Windows 8.1) In EditMeetingCtrl EditMeetingCtrl.save() should save the meeting FAILED
TypeError: $state is undefined in C:/Users/sal/Documents/myApp/test/meeting/EditMe
etingCtrlSpec.js (line 80)
我假设这是因为我没有在注入方法中这样做 -> $state : state
,所以我也尝试这样做但得到了同样的错误。我在这里错过了什么?
您可以模拟整个 $state
提供程序,然后在调用 save
:[=14 之前在 params
属性 中准确指定您想要的值=]
describe('in EditMeetingCtrl', function () {
// ...
beforeEach(angular.mock.module('myApp'));
beforeEach(angular.mock.module(function ($provide) {
// mock the entire $state provider
$provide.provider('$state', function () {
return {
$get: function () {
return {
// by default it will be an empty object
params: {}
};
}
};
});
}));
// ....
describe('EditMeetingCtrl.save()', function () {
// inject mocked $state - one that you've provided above
var $rootScope, scope, $controller, $q, state;
// ---------------------------------------^^^
beforeEach(inject(function ($rootScope, $controller, $state, _meetingService) {
// ------------------------------------------------^^^
state = $state;
}));
// ...
it("should save the meeting object", function() {
// provide custom params which will be used in a call
state.params = { companyId: 123, meetingId: 567 };
spyOn(meetingService, 'saveMeeting').and.returnValue(fakeHttpPromise);
scope.save();
expect(meetingService.saveMeeting).toHaveBeenCalledWith( meetingId , companyId , meetingObj);
});
});
// ...
});