How to wait until callback on appendFile work Jest

I have a method

private processWriteNextChunk(filePath: string): void {
    const nextChunk = this.data.get(filePath)?.shift();
    if (!nextChunk) return;
    appendFile(filePath, nextChunk.buffer, () => {
      nextChunk?.last ? this.data.delete(filePath) : this.emitWriteNextChunk(filePath);
    });
  }

And I'm testing it like

  it('should call appendFile when chunk array is not empty and delete data pair if it was last chunk',() => {
let appendFileCallback;
const appendFileSpy = jest.spyOn(fs, 'appendFile').mockImplementation((path, data, callback) => {
  appendFileCallback = callback;
});
const data: IBufferChunk = { ...MOCK_DATA, last: true };
service.data.set(MOCK_PATH, [data]);
service.processWriteNextChunk(MOCK_PATH);

expect(appendFileSpy).toHaveBeenCalledWith(MOCK_PATH, data.buffer, appendFileCallback);
expect(service.data.size).toBe(0);


});

test fails with

enter image description here

It happens because this.data.delete(filePath) doesn't have time to work, how I can fix this?

2 answers

  • answered 2021-01-14 11:05 yuval.bl

    If I understand correctly, processWriteNextChunk represent an async operation.

    So if you mark the function as async, and return a promise

     private async processWriteNextChunk(filePath: string): Promise<YOUR_TYPE> { 
        //...
        return appendFile(...)
     }
    

    Then, you can use await inside your jest it

    it('should call appendFile when chunk array is not empty and call emitWriteNextChunk if it wasn\'t last chunk', async () => {
        //...
        await service.processWriteNextChunk(MOCK_PATH);
    });
    

  • answered 2021-01-14 11:44 Alex Kirillov

    My problem was that mockImplementation function change the way how function works, so my callback haven't been called, so I just made it like

    const appendFileSpy = jest
          .spyOn(fs, 'appendFile')
          .mockImplementation((path, data, callback) => {
            callback(null);
            appendFileCallback = callback;
          });
    

    and it works fine