Jasmine 控制器和模拟服务没有被注入到单元测试中
Jasmine controller and mock service not being injected into the unit tests
这是我的 test_sp.js 文件:
describe('Controller: MainCtrl', function() {
var ctrl, mockBaseService;
beforeEach(function() {
mockBaseService = {
cerrorMessages: 'whatever',
sp: "[{'spName': 'Test'}]",
// Calls back if errors.
add: jasmine.createSpyObj('BaseService.add', ['sp']),
logout: jasmine.createSpy('BaseService.logout'),
// Calls back if errors.
fetch: jasmine.createSpyObj('BaseService.fetch', ['selfsp'])
};
mockBaseService.add.sp.and.callFake(function(something, cb) {
cb(); // execute the callback immediately
});
mockBaseService.fetch.selfsp.and.callFake(function(something, cb) {
cb(); // execute the callback immediately
});
module('SpPageApp');
// Let ctrl = MainCtrl and override BaseService in MainCtrl to be
// the mockBaseService above.
inject(function($controller) {
ctrl = $controller('MainCtrl', {
BaseService: mockBaseService
});
});
});
it('should have an add function', function() {
expect(ctrl.add).toBeDefined();
});
});
这是我的业力配置文件的 file
数组:
files: [
'../angular.js',
'node_modules/angular-mocks/angular-mocks.js',
'../w.js',
'../sp.js',
'../s.js',
'../base.js',
'tests/test_sp.js',
],
最后,这是我的 sp.js
,它有 SpPageApp
模块:
angular.module("SpPageApp", ["BaseApp"])
.controller("MainCtrl", ["$http", "$window", "BaseService", function($http, $window, BaseService) {
var self = this;
BaseService.fetch.selfsp(function() {
self.sp = BaseService.sp;
self.cerrorMessages = BaseService.cerrorMessages;
});
self.add = function() {
BaseService.add.sp(self.sp, function() {
self.cerrorMessages = BaseService.cerrorMessages;
});
};
self.logoutUser = function() {
BaseService.logout();
};
}]);
我做 karma start
来测试代码,我收到一条错误消息:
Chromium 47.0.2526 (Ubuntu 0.0.0) Controller: MainsCtrl should have an add function FAILED
TypeError: Cannot read property 'and' of undefined
at Object.<anonymous> (/home/a/Documents/CMS/CMSApp/static/js/karma/tests/test_sp.js:20:45)
TypeError: Cannot read property 'add' of undefined
at Object.<anonymous> (/home/a/Documents/CMS/CMSApp/static/js/karma/tests/test_sp.js:36:20)
Chromium 47.0.2526 (Ubuntu 0.0.0): Executed 1 of 1 (1 FAILED) (0 secs / 0.006 secChromium 47.0.2526 (Ubuntu 0.0.0): Executed 1 of 1 (1 FAILED) ERROR (0.034 secs / 0.006 secs)
报错说无法读取defined的属性 add
,指向这一行:
expect(ctrl.add).toBeDefined();
并且它无法读取未定义的属性 and
,并指向这一行:
mockBaseService.fetch.selfsp.and.callFake(function(something, cb) {
为什么 Jasmine 在代码中定义了 ctrl
和 mockBaseService.fetch.selfsp
却说它们是未定义的?
编辑:就其价值而言,w.js
、sp.js
和 s.js
(正在加载业力)都有名为 MainCtrl
的控制器,但每个控制器都在其中自己的文件和 AngularJS 模块(在 test_sp.js
中,我只加载 SpPageApp
模块)。
如我的评论所述,您可以直接模拟服务并避免使用间谍。此外,您可以告诉 $injector 使用您的模拟服务而不是真正的实现,允许您在解析服务时直接注入模拟,从而取代您的正常实现。
假设您的 BaseService 存在于 SpPageApp 模块中:
mockBaseService = {
cerrorMessages: 'whatever',
sp: "[{'spName': 'Test'}]",
add: function (something, cb) { cb() },
...
};
module('BaseApp', function($provide) {
$provide.value('BaseService', mockBaseService);
});
module('SpPageApp');
inject(function($controller) {
ctrl = $controller('MainCtrl', {
});
});
要测试它,如评论中所述,您仍然需要使用间谍来确保它被成功调用。
it('should have an add function', function() {
spyOn(mockBaseService, 'add');
ctrl.add();
expect(mockBaseService.add).toHaveBeenCalled();
});
这是我的 test_sp.js 文件:
describe('Controller: MainCtrl', function() {
var ctrl, mockBaseService;
beforeEach(function() {
mockBaseService = {
cerrorMessages: 'whatever',
sp: "[{'spName': 'Test'}]",
// Calls back if errors.
add: jasmine.createSpyObj('BaseService.add', ['sp']),
logout: jasmine.createSpy('BaseService.logout'),
// Calls back if errors.
fetch: jasmine.createSpyObj('BaseService.fetch', ['selfsp'])
};
mockBaseService.add.sp.and.callFake(function(something, cb) {
cb(); // execute the callback immediately
});
mockBaseService.fetch.selfsp.and.callFake(function(something, cb) {
cb(); // execute the callback immediately
});
module('SpPageApp');
// Let ctrl = MainCtrl and override BaseService in MainCtrl to be
// the mockBaseService above.
inject(function($controller) {
ctrl = $controller('MainCtrl', {
BaseService: mockBaseService
});
});
});
it('should have an add function', function() {
expect(ctrl.add).toBeDefined();
});
});
这是我的业力配置文件的 file
数组:
files: [
'../angular.js',
'node_modules/angular-mocks/angular-mocks.js',
'../w.js',
'../sp.js',
'../s.js',
'../base.js',
'tests/test_sp.js',
],
最后,这是我的 sp.js
,它有 SpPageApp
模块:
angular.module("SpPageApp", ["BaseApp"])
.controller("MainCtrl", ["$http", "$window", "BaseService", function($http, $window, BaseService) {
var self = this;
BaseService.fetch.selfsp(function() {
self.sp = BaseService.sp;
self.cerrorMessages = BaseService.cerrorMessages;
});
self.add = function() {
BaseService.add.sp(self.sp, function() {
self.cerrorMessages = BaseService.cerrorMessages;
});
};
self.logoutUser = function() {
BaseService.logout();
};
}]);
我做 karma start
来测试代码,我收到一条错误消息:
Chromium 47.0.2526 (Ubuntu 0.0.0) Controller: MainsCtrl should have an add function FAILED
TypeError: Cannot read property 'and' of undefined
at Object.<anonymous> (/home/a/Documents/CMS/CMSApp/static/js/karma/tests/test_sp.js:20:45)
TypeError: Cannot read property 'add' of undefined
at Object.<anonymous> (/home/a/Documents/CMS/CMSApp/static/js/karma/tests/test_sp.js:36:20)
Chromium 47.0.2526 (Ubuntu 0.0.0): Executed 1 of 1 (1 FAILED) (0 secs / 0.006 secChromium 47.0.2526 (Ubuntu 0.0.0): Executed 1 of 1 (1 FAILED) ERROR (0.034 secs / 0.006 secs)
报错说无法读取defined的属性 add
,指向这一行:
expect(ctrl.add).toBeDefined();
并且它无法读取未定义的属性 and
,并指向这一行:
mockBaseService.fetch.selfsp.and.callFake(function(something, cb) {
为什么 Jasmine 在代码中定义了 ctrl
和 mockBaseService.fetch.selfsp
却说它们是未定义的?
编辑:就其价值而言,w.js
、sp.js
和 s.js
(正在加载业力)都有名为 MainCtrl
的控制器,但每个控制器都在其中自己的文件和 AngularJS 模块(在 test_sp.js
中,我只加载 SpPageApp
模块)。
如我的评论所述,您可以直接模拟服务并避免使用间谍。此外,您可以告诉 $injector 使用您的模拟服务而不是真正的实现,允许您在解析服务时直接注入模拟,从而取代您的正常实现。
假设您的 BaseService 存在于 SpPageApp 模块中:
mockBaseService = {
cerrorMessages: 'whatever',
sp: "[{'spName': 'Test'}]",
add: function (something, cb) { cb() },
...
};
module('BaseApp', function($provide) {
$provide.value('BaseService', mockBaseService);
});
module('SpPageApp');
inject(function($controller) {
ctrl = $controller('MainCtrl', {
});
});
要测试它,如评论中所述,您仍然需要使用间谍来确保它被成功调用。
it('should have an add function', function() {
spyOn(mockBaseService, 'add');
ctrl.add();
expect(mockBaseService.add).toHaveBeenCalled();
});