mardi 2 février 2016

Inject real implementation of Angular's $timeout service in a Karma/Jasmine unit test

I have a small Angular service that handles asynchronous rate-limiting of other functions, similar to this example. Since the main purpose of this class is to moderate asynchronous behaviors, I'd like to be able to test this service asynchronously - I won't be able to prove that this class is working with a purely synchronous test.

If I understand correctly, when Angular's ngMock module is loaded, the built-in $timeout service is replaced with a mocked version of $timeout which allows tests to synchronously run functions that are ordinarily asynchronous. However, in this case, I'd like to use the real implementation of $timeout instead of the mocked version.

How can I inject the real implementation of $timeout into my unit test?

Here's what my tests looks like currently (I'm writing my tests in TypeScript):

describe('My Tests', () => {

    let myService: MyService,
        $timeout: ng.ITimeoutService;

    beforeEach(() => {
        inject(($injector) => {
            // this gets me the mocked version of $timeout
            $timeout = $injector.get('$timeout');
        });

        myService = new MyService($timeout);

        jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000;
    });

    it('should pass', (done) => {
        $timeout(50)
            .then(() => {
                // this is never called
                expect(1).toBe(1);
            })
            .finally(done);
    });

});

When I run this test, Karma complains that the test too took long because the mocked$timeout service never actually kicks off its deferred timeout:

Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.

Aucun commentaire:

Enregistrer un commentaire