How do you spy on AngularJS's $timeout with Jasmine?
angularjs, jasmine, spy, unit-testing
Solution
In angular `$timeout` is a service that executes/calls a function. The request to "spy" `$timeout` is a bit odd being the case that what it is doing is executing X function in Y given time. What I would do to spy this services is to "mock" the timeout function and inject it in your controller something like:
it('shouldvalidate time',inject(function($window, $timeout){
function timeout(fn, delay, invokeApply) {
console.log('spy timeout invocation here');
$window.setTimeout(fn,delay);
}
//instead of injecting $timeout in the controller you can inject the mock version timeout
createController(timeout);
// inside your controller|service|directive everything stays the same
/* $timeout(function(){
console.log('hello world');
x = true;
},100); */
var x = false; //some variable or action to wait for
waitsFor(function(){
return x;
},"timeout",200);
...
Problem
I am trying to spy on $timeout so that I can verify that it has not been called. Specifically, my production code (see below) calls $timeout as a function, not an object: ``` $timeout(function() { ... }) ``` and not ``` $timeout.cancel() // for instance ``` Jasmine, however, requires an object to be spied upon, like this: ``` spyOn(someObject, '$timeout') ``` I don't know what 'someObject' would be though. I am using Angular mocks, if that makes any difference. Edit: The relevant production code I'm trying to test looks like this: ``` EventHandler.prototype._updateDurationInOneSecondOn = function (call) { var _this = this; var _updateDurationPromise = this._$timeout(function () { call.duration = new Date().getTime() - call.startTime; _this._updateDurationInOneSecondOn(call); }, 1000); // ... more irrelevant code } ``` In the specific test scenario I am trying to assert that $timeout was never called. Edit 2: Specified clearly that I am using $timeout as a function, not an object.