Search code examples
node.jsjestjsmockingfs

How do I mock an fs.writeFile call with a promise using jest?


After trying many ways to do this, I've hit a brick wall. With the code I have now, once the fs.writeFile is dummied, the software throws the following error:

Error: ENOENT: no such file or directory (followed by the path and file).

A simple routine to write a file using fs:

'use strict';
const fs = require('fs').promises;
const path = require('path');

const writeData = async (data, file) => {
  const directoryPath = path.join(__dirname, '../wiremock/stubs/mappings');
  try {
    fs.writeFile(`${directoryPath}/${file}`, data);
    return `${file} written`
  } catch (err) {
    return err;
  }
};

The unit test:

'use strict';
const fs = require('memfs');
const path = require('path');
jest.mock('fs');

const {
  writeData,
} = require('../transform');

const directoryPath = path.join(__dirname, '../../wiremock/stubs/mappings');

describe('Write file', () => {
  it('should write a file', async () => {
    try {
      await fs.writeFile(`${directoryPath}/test-file`, 'test data');
      const result = await writeData('test data', 'test-file');
      expect(result).toEqual('test-file written')
    } catch (err) {
      console.log('error=', err);
    }
  });
});

Solution

  • You didn't mock the fs.promises correctly.

    index.js:

    const fs = require('fs').promises;
    const path = require('path');
    
    const writeData = async (data, file) => {
      const directoryPath = path.join(__dirname, '../wiremock/stubs/mappings');
      try {
        await fs.writeFile(`${directoryPath}/${file}`, data);
        return `${file} written`;
      } catch (err) {
        return err;
      }
    };
    
    module.exports = { writeData };
    

    index.test.js:

    const { writeData } = require('.');
    
    jest.mock('fs', () => ({
      promises: {
        writeFile: jest.fn(),
      },
    }));
    
    describe('Write file', () => {
      it('should write a file', async () => {
        const result = await writeData('test data', 'test-file');
        expect(result).toEqual('test-file written');
      });
    });
    

    Test result:

     PASS  stackoverflow/72115160/index.test.js
      Write file
        ✓ should write a file (3 ms)
    
    Test Suites: 1 passed, 1 total
    Tests:       1 passed, 1 total
    Snapshots:   0 total
    Time:        2.857 s, estimated 12 s