Testing a $interval with Jasmine in PhantomJS

jasmine, javascript, phantomjs

Solution

$interval has a mock implementation in angular-mocks. Make sure you are using a version of angular-mocks that matches your angular version.

The mock version of $interval has a flush method for controlling ticks. See ngMock.$interval

See this fiddle with a demonstration:

//--- CODE --------------------------
angular.module('myModule', []).service('myModuleService', ['$interval', function ($interval) {
    var called = 0;
    $interval(function () {
        called++;
    }, 10);
    this.getCalled = function () {
        return called;
    }
}]);

// --- SPECS -------------------------

describe('test $interval', function () {

    it('calls the interval callback', function () {
        var service, $interval;
        angular.mock.module('myModule');
        angular.mock.inject(function (myModuleService, _$interval_) {
            // Initialize the service under test instance
            service = myModuleService;
            $interval = _$interval_;
        });
        expect(service.getCalled()).toEqual(0);
        $interval.flush(11);
        expect(service.getCalled()).toEqual(1);
        $interval.flush(10);
        expect(service.getCalled()).toEqual(2);
    });
});

Problem

It appears that my `interval` is never triggered. I have a directive which contains a `$interval` and I want to test it. I've removed all the directive-related code and added this piece instead in its controller: ``` window.called = 0; window.interval = $interval(function () { window.called++; console.log('interval ' + window.called); // 4 }, 10); console.log('initialized'); // 1 ``` The test looks like this: ``` describe('myDirective', function () { beforeEach(module('myModule')); beforeEach(function($compile, $rootScope) { /* ... compile element in its own scope ... */ }); it('should run the interval', function () { console.log(window.interval); // 2 waitsFor(function () { console.log('tick'); // 3 return false; }, 1000); }); }); ``` This is a dumb test. The `waitsFor` method actually returns false all the time, for debugging purposes. But this is all I see in the console: ``` initialized // 1 Object: {then: ..} // 2 tick // 3 tick // 3 tick // 3 tick // 3 .. ``` and eventually the test failure. I never see a single `interval` in the logs. Is there something wrong with my code in general or is there something particular to Jasmine/PhantomJS that I'm missing?

Original source