I have an AngularJS directive I'm trying to test with Jasmine 2. Here's a Mock service that I have defined at the beginning my test.
var Note = {
getNotes: function (type, id) {
console.log('I have been called')
},
save: function () {}
};
And here's my test:
beforeEach(function () {
var html = "<notes id=\"productId\" type=\"'Product'\"></notes>";
inject(function ($compile, $rootScope, $q, $injector, $templateCache) {
$templateCache.put('tpl/blocks/notes.html', '<div>notes template</div>');
$scope = $rootScope.$new();
q = $q;
$httpBackend = $injector.get('$httpBackend');
$scope.productId = "123";
elm = angular.element(html);
$compile(elm)($scope);
$scope.$apply();
scope = angular.element(elm).isolateScope()
});
});
it('should call service to get notes', function () {
//GIVEN
expect(scope.notes).toBe(undefined);
spyOn(Note, 'getNotes').and.returnValue(new function () {
var deferred = q.defer();
scope.notes = [{'content': 'note1'}, {'content': 'note2'}];
return deferred.promise;
});
//WHEN
scope.$apply();
//THEN
expect(Note.getNotes).toHaveBeenCalled();
expect(scope.notes.length).toBe(2);
});
If I remove the first expect (where it expects Note.getNotes to get called), the test passes. Otherwise, it fails. However, I can see the service is getting called because it's printed with console.log.
INFO [karma]: Karma v0.12.35 server started at http://localhost:9876/
INFO [launcher]: Starting browser PhantomJS
INFO [PhantomJS 1.9.8 (Mac OS X 0.0.0)]: Connected on socket pPpiC59pcRGYeZDkmHH1 with id 30185266
WARN [web-server]: 404: /js/controllers/signin.js
......
LOG: 'I have been called'
PhantomJS 1.9.8 (Mac OS X 0.0.0) Notes directive should call service to get notes FAILED
Expected spy getNotes to have been called.
at /Users/mraible/dev/myapp/tests/unit/directives/notes_test.js:68
LOG: 'I have been called'
...
DUMP: 'background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(153, 255, 0); background-position: initial initial; background-repeat: initial initial; '
.
PhantomJS 1.9.8 (Mac OS X 0.0.0): Executed 11 of 11 (1 FAILED) (0.004 secs / 0.171 secs)
Warning: Task "karma:unit" failed. Use --force to continue.
Aborted due to warnings.
My hunch is that my spyOn has to change to indicate the method has arguments.
You would need to override the Notes
service in the module using provide.
Example:
var Note, notesStub = [{'content': 'note1'}, {'content': 'note2'}];
beforeEach(module('myapp', function($provide){
Note = jasmine.createSpyObj('Note',['getNotes', 'save']);
//override the service
$provide.value('Note', Note);
}));
beforeEach(inject(function($q){
//Set up spy value
Note.getNotes.and.returnValue($q.when(notesStub));
//Other inject stuffs
}));
it('should call service to get notes', function () {
//GIVEN
expect(scope.notes).toBe(undefined);
scope.$apply();
//Assuming your directive calls the service and chain though the promise and set its scope.
expect(Note.getNotes).toHaveBeenCalled();
expect(scope.notes.length).toBe(2);
});