Reputation: 573
So I'm learning how to test in Angular and followed a tutorial that showed how to mock out the services that your controller uses. Can't seem to figure out why it isn't working so I'm turning here for help. Any advice on what I'm doing wrong and how to get it working would be greatly appreciated.
Error: Expected a spy, but got Function.
// Controller
'use strict';
angular.module('tikrApp')
.controller('MessageCtrl', ['$scope', '$state', 'messageService', function ($scope, $state, messageService) {
/**
* Set $state on the scope to access it in the views
*/
$scope.$state = $state;
/**
* Fetches a messages list that belongs to the authenticated user
*/
$scope.inbox = function () {
messageService.inbox().then(function (messages) {
$scope.messages = messages;
});
};
/**
* Fetches a message
*/
$scope.show = function (message) {
messageService.update(message, { read: true }).then(function (result) {
if (result) {
$scope.message = message;
$scope.message.read = true;
}
});
};
/**
* Prioritizes the message for the user
*/
$scope.starred = function (message) {
messageService.update(message, { starred: true }).then(function (result) {
if (result) message.starred = true;
});
};
/**
* Creates a new private message to a user
*/
$scope.create = function (newMessage) {
messageService.create(newMessage).then(function () {
$scope.messages.push(newMessage);
$state.transitionTo('inbox.messages');
}, function () {
$state.transitionTo('inbox.messages.create');
});
};
$scope.inbox();
// $state.transitionTo('inbox.messages');
}]);
// Spec
'use strict';
describe('Controller: MessageCtrl', function () {
var scope;
var messageService;
beforeEach(function () {
var mockMessageService = {};
module('tikrApp', function ($provide) {
$provide.value('messageService', mockMessageService);
});
inject(function ($q) {
mockMessageService.messages = [
{ to: '123', from: '123', title: 'Title 1', content: 'Content 1', read: false },
{ to: '123', from: '123', title: 'Title 2', content: 'Content 2', read: false },
{ to: '123', from: '123', title: 'Title 3', content: 'Content 3', read: false }
];
mockMessageService.inbox = function () {
var defer = $q.defer();
defer.resolve(this.messages);
return defer.promise;
};
mockMessageService.create = function (newMessage) {
var defer = $q.defer();
defer.resolve();
return defer.promise;
};
});
});
beforeEach(inject(function ($controller, $rootScope, _messageService_) {
scope = $rootScope.$new();
messageService = _messageService_;
$controller('MessageCtrl', {
$scope: scope,
messageService: messageService
});
scope.$digest();
}));
it('should list all messages in the users inbox', function () {
// tried this way
spyOn(scope, 'inbox');
// and this way
spyOn(messageService, 'inbox');
expect(messageService.inbox).toHaveBeenCalled();
});
});
Upvotes: 0
Views: 999
Reputation: 328
This's how I usually unit test controller-service communication. I find this approach easier:
'use strict';
describe('countryController', function () {
var scope;
var searchService;
beforeEach(module('app'));
beforeEach(inject(function ($controller, $rootScope) {
scope = $rootScope.$new();
mockSearchService();
createController($controller);
}));
it('loads flights after view is shown', function () {
scope.loadFlights();
expect(searchService.loadFlights).toHaveBeenCalled();
});
function mockSearchService() {
searchService = jasmine.createSpyObj('searchService', ['loadFlights']);
}
function createController($controller) {
$controller('countryController', {
$scope: scope,
searchService: searchService
});
}
});
Upvotes: 1