per.eight
per.eight

Reputation: 436

How to test a method with timeout after calling another method in sinon

How can I test a property inside a timeout from another called method?

I want to test a property if it's changed inside the setTimeout but using sinons useFakeTimer doesn't seems to work. Or am I missing something?

To illustrate here's my code

const fs = require('fs');

function Afunc (context) {
    this.test = context;
}

module.exports = Afunc;

Afunc.prototype.start = function () {
    const self = this;

    this.readFile(function  (error, content) {
        setTimeout(function () {
            self.test = 'changed';
            self.start();
        }, 1000);
    });
}

Afunc.prototype.readFile = function (callback) {
    fs.readFile('./file', function (error, content) {
        if (error) {
            return callback(error);
        }

        callback(null, content);
    })
}

And here's what I have so far.

describe('Afunc', function () {
    let sandbox, clock, afunc;

    before(function () {
        sandbox = sinon.createSandbox();
    });

    beforeEach(function () {
        clock = sinon.useFakeTimers();

        afunc = new Afunc('test');

        sandbox.stub(afunc, 'readFile').yieldsAsync(null);
    });

    afterEach(function () {
        clock.restore();
        sandbox.restore();
    });

    it('should change test to `changed`', function () {
        afunc.start();

        clock.tick(1000);

        afunc.test.should.be.equal('changed');

    });
});

after the clock.tick check the property test is not changed.

Any help is deeply appreciated! Thanks in advance.

Upvotes: 1

Views: 226

Answers (1)

Brian Adams
Brian Adams

Reputation: 45810

Just change this:

sandbox.stub(afunc, 'readFile').yieldsAsync(null);

...to this:

sandbox.stub(afunc, 'readFile').yields();

...and it should work.


Details

yieldsAsync defers using process.nextTick so the callback passed to readFile wasn't getting called until "all instructions in the current call stack are processed"...which in this case was your test function.

So the callback that changed afunc.test to 'changed' was getting called...but not until after your test completed.

Upvotes: 1

Related Questions