How do you spy on AngularJS's $timeout with Jasmine?

浪尽此生 提交于 2019-12-22 05:41:11

问题


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.


回答1:


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);

...



回答2:


Ran into the same problem and ended up decorating the $timeout service with a spy.

beforeEach(module(function($provide) {
    $provide.decorator('$timeout', function($delegate) {
        return sinon.spy($delegate);
    });
}));

Wrote more about why this works here.




回答3:


This code works for me

var element, scope, rootScope, mock = {
    timeout : function(callback, lapse){
        setTimeout(callback, lapse);
    }
};

beforeEach(module(function($provide) {
    $provide.decorator('$timeout', function($delegate) {
      return function(callback, lapse){
          mock.timeout(callback, lapse);
          return $delegate.apply(this, arguments);
      };
    });
}));
describe("when showing alert message", function(){

    it("should be able to show message", function(){
        rootScope.modalHtml = undefined;
        spyOn(mock, 'timeout').and.callFake(function(callback){
            callback();
        });
        rootScope.showMessage('SAMPLE');

        expect(rootScope.modalHtml).toBe('SAMPLE');

    });

});


来源:https://stackoverflow.com/questions/20345552/how-do-you-spy-on-angularjss-timeout-with-jasmine

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!