bgmn
bgmn

Reputation: 508

How to mock JSON file in Jest

I am using Jest to test my API and when I run my tests, my JSON file results.json gets written to due to the following line in my API app.js (which I don't want happening):

fs.writeFile('results.json', JSON.stringify(json), (err, result) => {
    if (err) console.log('error', err);
});

This is what my Jest file looks like:

const request = require('supertest');
const app = require('./app');


// Nico Tejera at https://stackoverflow.com/questions/1714786/query-string-encoding-of-a-javascript-object
function serialise(obj){
    return Object.keys(obj).map(k => `${encodeURIComponent(k)}=${encodeURIComponent(obj[k])}`).join('&');
}


describe('Test /addtask', () => {
    test('POST /addtask Successfully redirects if newDate and newTask filled in correctly', () => {
        const params = {
                    newTask: 'Example',
                    newDate: '2020-03-11'
        };
        return request(app)
            .post('/addtask')
            .send(serialise(params))
            .expect(301);
    });
});

I tried creating a mock of the JSON file and placed it outside the describe statement to prevent the actual results.json file being written to:

jest.mock('./results.json', () => ({ name: 'preset1', JSONtask: [], JSONcomplete: [] }, { name: 'preset2', JSONtask: [], JSONcomplete: [] }));

But this doesn't change anything. Does anyone have any suggestions?

I have seen other solutions to similar problems but they don't provide the answer I'm looking for.

EDIT: Although not a very good method, one solution to my problem is to wrap the fs.writeFile within the statement

if (process.env.NODE_ENV !== 'test') {
//code
};

although this would mean that fs.writeFile cannot be tested upon.

NOTE: I am still accepting answers!

Upvotes: 1

Views: 4905

Answers (2)

Nino Filiu
Nino Filiu

Reputation: 18493

jest.mock(path, factory) is for mocking JS modules, not file content.

You should instead mock fs.writeFile and check that it has been called with the expected arguments. The docs explain how to do it.

Upvotes: 1

fjc
fjc

Reputation: 5815

Your issue is that the code you want to test has a hard-coded I/O operation in it, which always makes things harder to test.

What you'll want to do is to isolate the dependency on fs.writeFile, for example into something like a ResultsWriter. That dependency can then be injected and mocked for your test purposes.

I wrote an extensive example on a very similar case with NestJS yesterday under how to unit test a class extending an abstract class reading environment variables, which you can hopefully adapt to your needs.

Upvotes: 1

Related Questions