I have in my controller $rootScope.$on function which listen for user login
$rootScope.$on('$firebaseSimpleLogin:login',function(e, authUser) {
User.findByUid(authUser.uid).then(function(user) {
I mocked 'User' and 'loginService' service.
beforeEach(inject(function($controller, $rootScope, $q) {
scope = $rootScope.$new();
q = $q;
headerCtrl = $controller('headerCtrl', {
$scope: scope,
loginService: _loginService,
User: _userService
});
}));
And now I want to test that User.findByUid will be called when $on catch user login. So I need to know how to "mock-simulate" this $on method so I can check if the findByUid method was called. How please? I tried something like...
it('should call User.findByUid on $firebaseSimpleLogin:login', function() {
spyOn(scope, '$on');
// here I need to probably trigger it somehow...
// and check or?...
expect(scope.$on).toHaveBeenCalled();
});
UPDATE https://gist.github.com/TrkiSF2/39315e7ea980cac6cc9f
SIDE QUESTION
When I change my ctrl code to:
$rootScope.$on('$firebaseSimpleLogin:login',function(e, authUser) {
User.findByUid(authUser.uid);
});
And my mock user service to:
findByUid: function(uid) {
console.log("dump");
}
And my test to:
it('should call User.findByUid on $firebaseSimpleLogin:login', function() {
spyOn(_userService, 'findByUid');
var authUser = { uid: 1 };
scope.$emit('$firebaseSimpleLogin:login', authUser);
expect(_userService.findByUid).toHaveBeenCalled();
});
It works... but why there is no "dump" message in console so I can be sure the test used my mocked code and no the real one. (lets say I would like to be sure it will not execute some DB queries if there are...)
Last question
What if my ctrl code looks like:
$rootScope.$on('$firebaseSimpleLogin:login',function(e, authUser) {
User.findByUid(authUser.uid).then(function(user) {
User.setCurrentUser(user);
And I would like to check if the User.setCurrentUser is called as well? What is the best way to do it? In some separate code or somehow in the same?
MAYBE ANSWER FOR MY QUESTION?
I tried just from curiosity what this will do and i added new method to my mocked user object:
setCurrentUser: function(user) {
}
I have resolved my promise:
findByUid: function(uid) {
defered = q.defer();
defered.resolve({nick:'Trki'});
return defered.promise;
},
Then I updated my test
it('should call User.findByUid on $firebaseSimpleLogin:login', function() {
spyOn(_userService, 'findByUid').and.callThrough();
spyOn(_userService, 'setCurrentUser');
var authUser = { uid: 1 };
scope.$emit('$firebaseSimpleLogin:login', authUser);
scope.$root.$digest();
expect(_userService.findByUid).toHaveBeenCalled();
expect(_userService.setCurrentUser).toHaveBeenCalled;
});
And it says success! Is this the good way?
Spy on the User mock:
spyOn(_userService, 'findByUid').and.callThrough();
Then dispatch the event manually with $broadcast or $emit (depending on which scope you dispatch from). Add arguments if needed:
var authUser = { uid: 1 };
scope.$emit('$firebaseSimpleLogin:login', authUser);
Do the verification:
expect(_userService.findByUid).toHaveBeenCalled();
You need to use and.callThrough() in this case since you have a then added to the chain here:
User.findByUid(authUser.uid).then(function(user) {
And if not letting the call through your mock will not return the promise you have defined:
findByUid: function(uid) {
defered = q.defer();
return defered.promise;
}
And it will try to perform the then on undefined, hence the "'undefined' is not an object".
SIDE QUESTION - Answer:
If you add .and.callThrough(); the console.log("dump") should execute.
If you don't, the call will be intercepted, information about the call will be saved, but the function will not actually execute.
This means that if you are spying on own mocks you almost always want to use callThrough() since it's returning mocked data.
This also means that you don't always need own mocks, as you can just set up a spy on your service, and the real implementation will not be executed as the call will be intercepted.
You can then use and.returnValue and and.callFake to return or perform mocked logic.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With