Shared utils functions for testing with Jest

JavascriptReactjsJestjs

Javascript Problem Overview


I have some utils functions that I'm using among various Jest tests, for example a function like this, for mocking a fetch response:

export const mockFetchJsonResponse = (data) => {
    ok: () => true,
    json: () => data
};

I would like to share those functions in a way that I can import them and reuse among my tests. For example:

// Some .spec.jsx file
// ...
import {mockFetchJsonResponse} from 'some/path/to/shared/tests/utils.jsx'
    
// Then I can use mockFetchJsonResponse inside this test
// ...

Where should I place such common utils functions?

My project folder looks like this:

components/
    CompOne/
        __tests__
        index.jsx
    CompTwo/
        __tests__
        ...
utils/
    __tests__
    http.js
    user.js
    ...

Should I place them inside the utils folder together with other utils functions that I use for my project? Then should I write unit tests also for these functions?

Javascript Solutions


Solution 1 - Javascript

There is an ability to expose helpers as global functions without any need to import modules explicitly.

  1. Jest allows to configure some files will be run before every test file executed through setupFiles configuration option
  2. Also Jest provides global object that you can modify and everything you put there will be available in your tests.
Example

package.json:

"jest": {
    "setupFiles": ["helpers.js"]
} 

helpers.js:

global.mockFetchJsonResponse = (data) => {
    ok: () => true,
    json: () => data
};

somecomponent.test.js:

mockFetchJsonResponse(); // look mom, I can call this like say expect()!
With TypeScript

TypeScript will complain with cannot find name 'mockFetchJsonResponse'. You can fix that by adding a declaration file:

helpers.d.ts:

declare function mockFetchJsonResponse(data: any): any;

Create a new tsconfig.test.json file and add that file to the files section and extend your main tsconfig:

{
    "extends": "./tsconfig.json",
    "files": ["./.jest/helpers.d.ts"]
}

In your jest.config.js file, add a new global setup for ts-jest to have jest use your new tsconfig file:

// ...
globals: {
    "ts-jest": {
         tsconfig: "tsconfig.test.json"
    }
}
// ...

Sure it does not answer you direct question "where to put the files" but it's anyway up to you. You just need specify those files in setupFiles section. Since there is no import needed in tests it does not really matter.

As for testing test helpers I'm not sure. See it's part of testing infrastructure like spec file itself. And we don't write tests for tests or it would never stop. Sure, it's up to you - say if logic behind is really-really complex and hard to follow. But if helper provides too complex/complicated logic it would lead to tests themselves be impossible to understand, do you agree?

kudos to that article on testing compoentns with intl. Have never dealt with globals in jest before.

Solution 2 - Javascript

Another approach is by having a test directory and moving helpers on it.

src/
  components/
  utils/
  ...
test/
  testHelpers.js

Then on the test:

// src/components/MyComponent.spec.js
import { helperFn } from '../../test/testHelpers';

Benefits:

  • Be explicit of where the function is coming from
  • Separate helpers that need to be tested from those that do not ¹

Drawbacks:

  • The test directory might look silly by containing just a helper file
  • AFAIK this approach is no where specified on official documentation

Looks like GitLab is implementing this approach on their RoR project.

¹ no matter which approach you take, please don't test the test helpers. If the helper fails then your test must fail too. Otherwise your helper is not helping at all.

Solution 3 - Javascript

TL;DR; create a /__utils__/ and update testPathIgnorePatterns

Full answer:

Here's just a suggestion:

testPathIgnorePatterns: ['/__fixtures__/', '/__utils__/'],

I use /__tests__/ for the tests and within it sometimes I need to add a folder with data that will be used by those tests, so I use /__fixtures__/ folder.

Likewise, when I have a shared logic across tests, I place them at /__utils__/ folder (also within /__tests__/)

For more details, please read more about testPathIgnorePatterns

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAndreaView Question on Stackoverflow
Solution 1 - JavascriptskyboyerView Answer on Stackoverflow
Solution 2 - JavascriptLucioView Answer on Stackoverflow
Solution 3 - JavascriptawdkView Answer on Stackoverflow