Reputation: 2639
I am writing an app in AngularJS 1.5, JavaScript and Cordova.
I want to write a unit test that will check to see if some code was executed after a promise.
Here is my codepen: https://codepen.io/aubz/pen/yrxqxE
I am not sure why but the unit test keeps saying this error: Expected spy attemptGeoClocking to have been called.
It's strange because the console log prints out so the function is actually being called.
it('if location services are on, proceed', function () {
spyOn(CordovaDiagnostics, 'getLocationServicesStatus').and.callFake(function () {
return Promise.resolve(true);
});
spyOn(Clocking, 'attemptGeoClocking').and.callFake(function () {});
Clocking.geolocationClocking();
expect(Clocking.attemptGeoClocking).toHaveBeenCalled();
});
function geolocationClocking() {
CordovaDiagnostics
.getLocationServicesStatus()
.then(attemptGeoClocking)
.catch(function () {});
}
function attemptGeoClocking() {
console.log(' here ');
}
Upvotes: 0
Views: 614
Reputation: 1509
Basically you're spying on the wrong functions. Let me rename a few things so it's more clear what you're doing:
function Clocking(CordovaDiagnostics) {
return {
geolocationClocking: geolocationClocking,
attemptGeoClockingOUTER: attemptGeoClockingINNER//private API
};
function geolocationClocking() {
CordovaDiagnostics
.getLocationServicesStatus()
.then(attemptGeoClockingINNER)
.catch(function () {});
}
function attemptGeoClockingINNER() {
console.log(' here ');
}
}
And in the test:
spyOn(Clocking, 'attemptGeoClockingOUTER').and.callFake(function () {
console.log('calling fake')
});
As you can see, your code is spying on the OUTER
but geolocationClocking
is never calling the OUTER, it's using the INNER:
CordovaDiagnostics
.getLocationServicesStatus()
.then(attemptGeoClockingINNER)
You'll need to rework your code in such a way that it's using the same function internally as to the one you're stubbing in your test. Here's a working codepen: https://codepen.io/anon/pen/xeyrqy?editors=1111
Note: I've also replaced Promise.resolve
with $q.when
and added $rootScope.$apply()
, this is needed to resolve the promises.
Adding the changes I made here, in case the codepen would ever disappear:
I've changed the factory to a service (while not necessary, I prefer using services in this case):
myApp.service("Clocking", Clocking);
function Clocking(CordovaDiagnostics) {
this.geolocationClocking = function() {
CordovaDiagnostics
.getLocationServicesStatus()
.then(() => this.attemptGeoClocking())
.catch(function () {});
}
this.attemptGeoClocking = function() {
console.log(' here ');
}
}
Upvotes: 1