Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing async (Promise) methods in Angular 2 Services

This is an interesting problem: I'm trying to test a Service, that uses the Ionic BarcodeScanner. I have a repo based on the ionic unit-testing repository in order to try testing. I'm mocking the BarcodeScanner.scan method via spyOn(..).and.callFake(..)

The Problem: It works when I call the scan method from a component. It throws a timeout when I do the exact same thing in a service.

Component test code:

it("should be able to set a spy on the scanner and test the component", done => {
    const testBC = "123456";
    const spy = spyOn(TestBed.get(BarcodeScanner), "scan");
    spy.and.callFake(() => {
        return new Promise((resolve, reject) => {
            resolve(testBC);
        })
    });

        component.testScanner().then(res => {
            expect(res).toBe(testBC);
            done();
        }, reason => {
            expect(true).toBe(false);
            done();
        })
});

Service test code:

it("should be able to set a spy on the scanner and test the service", done => {
    const testBC = "123456";
    const spy = spyOn(TestBed.get(BarcodeScanner), "scan");
    spy.and.callFake(() => {
        return new Promise((resolve, reject) => {
            resolve(testBC);
        })
    });

    inject([TestService], (service) => {
        service.testScanner().then(res => {
            expect(res).not.toBe(testBC);
            done()
        }, reason => {
            expect(true).toBe(false);
            done();
        })
    })
});

Is there any known problem of testing services in Angular 2 that way? Any help appreciated!

like image 578
Sentenza Avatar asked Dec 04 '17 11:12

Sentenza


People also ask

What is the difference between async ()' and fakeAsync ()'?

tl;dr. In almost all cases, they can be used interchangeably, but using fakeAsync()/tick() combo is preferred unless you need to make an XHR call, in which case you MUST use async()/whenStable() combo, as fakeAsync() does not support XHR calls. For the most part they can be used interchangeably.

What is async in Angular testing?

async and whenStable We place the tests we need to run after the isAuthenticated promise resolves inside this function. This async function executes the code inside its body in a special async test zone. This intercepts and keeps track of all promises created in its body.

What is tick () in Angular?

The tick() function simulates the asynchronous passage of time for the timers in the fakeAsync zone in Angular test.


1 Answers

The problem was to not call the inject function.

The test code for the service now looks like this:

it("should be able to set a spy on the scanner and test the service", done => {
    const testBC = "123456";
    const spy = spyOn(TestBed.get(BarcodeScanner), "scan");
    spy.and.callFake(() => {
        return new Promise((resolve, reject) => {
            resolve(testBC);
        })
    });

    inject([TestService], (service) => {
        service.testScanner().then(res => {
            expect(res).not.toBe(testBC);
            done()
        }, reason => {
            expect(true).toBe(false);
            done(); 
        })
    })(); //<-- do not forget these braces!!
});
like image 154
Sentenza Avatar answered Sep 27 '22 18:09

Sentenza