Reputation: 22777
This is my test_sp.js file:
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();
});
});
And this is my karma config file's file
array:
files: [
'../angular.js',
'node_modules/angular-mocks/angular-mocks.js',
'../w.js',
'../sp.js',
'../s.js',
'../base.js',
'tests/test_sp.js',
],
Lastly, this is my sp.js
which has the SpPageApp
module:
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();
};
}]);
The I do karma start
to test the code, I get an error saying this:
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)
The error says it cannot read the property add
of defined, and points to this line:
expect(ctrl.add).toBeDefined();
and that it cannot read the property and
of undefined, and points to this line:
mockBaseService.fetch.selfsp.and.callFake(function(something, cb) {
How come Jasmine is saying both ctrl
and mockBaseService.fetch.selfsp
are undefined when they are defined in the code?
Edit: For what it's worth, w.js
, sp.js
and s.js
(which karma is loading) all have controllers called MainCtrl
but each controller is in it's own file and AngularJS module (and in test_sp.js
, I only load the SpPageApp
module).
Upvotes: 1
Views: 1542
Reputation: 33873
As mentioned in my comments, you can instead mock the service directly and avoid using spies. In addition, you can tell the $injector to use your mock service instead of the real implementation, allowing you to inject the mock directly when resolving the service, which replaces your normal implementation.
Assuming that your BaseService exists in the SpPageApp module:
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', {
});
});
To test it, as mentioned in the comments, you would still want to use a spy to make sure that it was successfully called.
it('should have an add function', function() {
spyOn(mockBaseService, 'add');
ctrl.add();
expect(mockBaseService.add).toHaveBeenCalled();
});
Upvotes: 2