How to expect().toHaveBeenCalled on a function from a mocked function

I have a function that simply creates a write stream and writes to it… I want to test that function, and test that the write() function of createWriteStream was called. However, I am mocking the fs module since I don’t want to actually write to a file while testing.

I can successfully check whether createWriteStream was called, but not write… why is that?

Code

const myFunction = () => {
  const stream = fs.createWriteStream("test.csv", {
    encoding: "utf8"
  });

  stream.write("hello world");
  stream.end();
}

Test

const fs = require("fs");

jest.mock("fs", () => ({
  createWriteStream: jest.fn(() => ({
    write: jest.fn(),
    end: jest.fn()
  }))
}));

describe("myFunction", () => {
  it("should write a new file", () => {
    myFunction();

    expect(fs.createWriteStream).toHaveBeenCalled(); //Passes

    expect(fs.createWriteStream().write).toHaveBeenCalled(); //Fails
  });
});

Answer

you can do something like below. In such way, the reference of writeMock will not be generated on the fly (which it is in your example, so jest can’t refer to the correct write method) and jest detect whether the function has been invoked through the reference.

jest.mock("fs");
describe('myFunction', () => {
  it('should write a new file', () => {
    const writeMock = jest.fn()
    const endMock = jest.fn()

    fs.createWriteStream = jest.fn(() => ({
      write: writeMock,
      end: endMock,
    }));
    myFunction();

    expect(fs.createWriteStream).toHaveBeenCalled(); //Passes

    expect(writeMock).toHaveBeenCalled(); //Passes
  });
});

Leave a Reply

Your email address will not be published. Required fields are marked *