Sinon - stub async function which is called from setInterval

Viewed 20

I want to test a class, which contains a private function (Bar), which is called from setInterval. This private function is async and requires a sleep function.

Class I want to test

export class Foo
{
    constructor ()
    {
        setInterval(async () => await this.Bar(), 1000);
    }

    private async Bar()
    {
        this.A();
        await this.sleep(5000);
        this.B();
    }

    private A()
    {
        console.log("A");
    }

    private B()
    {
        console.log("B");
    }

    public async sleep(ms: number)
    {
        return new Promise(resolve => setTimeout(resolve, ms));
    }
}

Mocha test

it.only("test", () =>
{
    let cut = new Foo();

    let ASpy = sinon.spy(cut, 'A');
    let BSpy = sinon.spy(cut, 'B');       
    sinon.stub(cut, 'sleep').resolves();
    
    fakeClock.tick(1000);

    ASpy.should.be.calledOnce;
    BSpy.should.be.calledOnce;

    ASpy.restore();
    BSpy.restore();
});

The test above fails, because function B is called too late. Result is:

A
    1) test
B

When I modify the code, that it doesn't use the setIntervall it works.

Any hint how to get this test work?

Thanks in advance.

1 Answers

I found a "dirty" solution for my issue. Following test works as I want:

it.only("test", (done) =>
    {
        let cut = new Foo();

        let ASpy = sinon.spy(cut, 'A');
        let BSpy = sinon.spy(cut, 'B');
        sinon.stub(cut, 'sleep').resolves();

        fakeClock.tick(1000);

        fakeClock.restore(); // restore timer so that following setTimeout works

        setTimeout(() =>
        {
            ASpy.should.be.calledOnce;
            BSpy.should.be.calledOnce;

            ASpy.restore();
            BSpy.restore();
            done();
        }, 0);
    });
Related