lulliezy
lulliezy

Reputation: 2063

Testing functions with properties using Jest and Sinon

am trying to write tests to test streams on my app, dealing with fs library with its createWriteStream function, so the stub i created is as follows:

writeStreamStub = sinon.stub()
onceStreamEventStub = sinon.stub()
endStreamStub = sinon.stub()
onStreamStub = sinon.stub()

createStreamStub = sinon.stub(fs, 'createWriteStream').returns({
  write: writeStreamStub,
  once: onceStreamEventStub,
  end: endStreamStub,
  on: onStreamStub
})

So now I can test for whether the functions are called and the returned functions are also called. But I am using the --coverage flag and the code of the callbacks of the returned functions is not covered, the write method is called inside a process.nextTick and I have no idea how to go about this. Is it possible to cover the whole code and the code inside the callbacks, and if so, how do I go about it. Thanks in advance.

N.B. The variables are globaly declared

Upvotes: 1

Views: 1369

Answers (1)

eol
eol

Reputation: 24565

If there's no cogent reason to use both sinon and jest, I'd recommend just using one library. If you decide to go with jest, here's a simple example. Assume you have a class like

const fs = require('fs');

module.exports = class FileWriter {
  constructor() {
    this.writer = fs.createWriteStream('./testfile.txt');
  }

  writeFile() {
    process.nextTick(() => {
      this.writeContent('hello world');
    });
  }

  writeContent(content) {
    this.writer.write(content);
    this.writer.end();
  }

};

and in your unit-test you want to mock the behaviour of all the used fs-functions (createWriteStream, writer, end in this case) and just check if they are called with the correct arguments. You could do this with something like this:

const fs = require('fs');
const FileWriter = require('./FileWriter');
// use this to have mocks for all of fs' functions (you could use jest.fn() instead as well)
jest.mock('fs');
describe('FileWriter', () => {
  it('should write file with correct args', async () => {
    const writeStub = jest.fn().mockReturnValue(true);
    const endStub = jest.fn().mockReturnValue(true);
    const writeStreamStub = fs.createWriteStream.mockReturnValue({
      write: writeStub,
      end: endStub,
    });

    const fileWriter = new FileWriter();
    fileWriter.writeFile();
    await waitForNextTick();
    expect(writeStreamStub).toBeCalledWith('./testfile.txt');
    expect(writeStub).toBeCalledWith('hello world');
    expect(endStub).toHaveBeenCalled();
  });
});

function waitForNextTick() {
  return new Promise(resolve => process.nextTick(resolve));
}

Upvotes: 1

Related Questions