Conditionally run tests with or without mocks with jest

Viewed 1753

I'm running tests with mocks so that the tests don't always hit APIs. I however also want to add a condition, so that I can use the same test to tests the APIs.

When I however add a condition, it ignores it and never applies the mocks no matter if the condition is true or false.

import config from 'config';
if(!config.test.useNetwork) {
    jest.mock('api/companies');
    jest.mock('api/articles');
}

import { searchCompany } from 'api/companies';
...

Two questions:

  1. Any idea for how to add conditional mocks? I think mocks never apply because jest.mock might need to be called before any imports?
  2. What's the convention for testing over the network? If I just use mocks, I'm really just testing the mocks, and not the network request code. But if I don't use mocks I'm unnecessarily hitting the API.
2 Answers

One:

Yes, jest.mock() is "hoisted to the top of the code block". However, jest.doMock is not hoisted. So, you can accomplish what you want thus:

const config = require('./config').default;
if(!config.test.useNetwork) {
    jest.doMock('api/companies');
    jest.doMock('api/articles');
}

const { searchCompany } = require('api/companies');

Two:

That's a controversial question. It isn't suited for StackOverflow and I'm not touching it lol

I had a similar question that I have answered for myself and a found another solution.

You can use the second parameter (factory) to decide whether you want to return a mock or the actual module

import config from 'config';
import { searchCompany } from 'api/companies';

jest.mock('api/companies', () => {
  if(!config.test.useNetwork) return jest.genMockFromModule('api/companies');
  return jest.requireActual('api/companies');
});
Related