Reputation: 1199
I'm using AngularJS, Karma, Mocha, Chai, Chai-as-promised, Sinon.
I'm trying the controller below. I am having trouble mocking the service User and test the .then() sections in the controller.
Controller Code
.controller('SignupPhoneCtrl', function(User, $scope) {
$scope.sendPhoneNumber = function(countryCode, phoneNumber){
User.sendPhoneNumber(countryCode, phoneNumber)
.then(function(result){
if(result == "success"){
//I WANT TO TEST THIS SECTION
return "success";
}
//I WANT TO TEST THIS SECTION
return "fail";
});
}
})
ControllerTest Code
describe('Controller: Signup-phone', function() {
var scope;
var UserMock;
var SignupPhoneCtrl;
beforeEach(function() {
module('starter.controllers');
});
beforeEach(inject(function($rootScope, $controller, $q){
scope = $rootScope.$new();
UserMock = {
sendPhoneNumber: function(countryCode, phoneNumber){
var deferred = $q.defer();
// console.log("called"); //This part is being called
deferred.resolve('foo');
return deferred.promise;
}
};
SignupPhoneCtrl = $controller("SignupPhoneCtrl", {$scope: scope, User: UserMock});
}))
it('should return asdf', function(){
scope.$digest();
//WHAT SHOULD I WRITE HERE?
})
});
I have tried the below but the assertion part is not being called.
scope.sendPhoneNumber(12, 53452123).then(function(result){
result.should.equal("fail"); //THIS SECTION IS NOT CALLED
})
I have tried the below, but it gives error: 'undefined' is not a function (evaluating 'promise.then.bind(promise)'
scope.sendPhoneNumber(12, 53452123).should.eventually.equal("fail");
sendPhoneNumber(12, 53452123)
returns Object{$$state: Object{status: 0}}
I tried to add sinon.spy(UserMock, 'sendPhoneNumber')
, but it makes no difference.
Upvotes: 4
Views: 1643
Reputation: 165070
The problem is, $scope.sendPhoneNumber
doesn't return anything. Try
return User.sendPhoneNumber(...
in your controller method.
Also, if you're just going to instantly resolve the promise in your mock, I've found this works nicely and saves you setting up a deferred object
UserMock = {
sendPhoneNumber: function(countryCode, phoneNumber){
return $q.when('foo');
}
};
That being said, you probably want to be able to control the resolved value in each test so this makes more sense...
var scope;
var UserMock;
var SignupPhoneCtrl;
var deferred;
// snip
inject(function($rootScope, $controller, $q) {
deferred = $q.defer();
UserMock = {
sendPhoneNumber: function() {
return deferred.promise;
}
};
});
// snip
it('tests for success', inject(function($rootScope) {
deferred.resolve('success');
scope.sendPhoneNumber(...).then(...);
$rootScope.$apply();
}));
it('tests for failure', inject(function($rootScope) {
deferred.resolve('not success');
scope.sendPhoneNumber(...).then(...);
$rootScope.$apply();
}));
Upvotes: 1