Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jest Manual Mocks with React and Typescript: mock an ES6 class dependency

I am completely new to Jest.

I am using React with Typescript and in a unit test I have to mock a module which is included inside the main file to which I am writing unit tests for (a container component).

The file I am trying to test imports this module:

import PerformancesResultsReader from './../../models/PerformancesResultsReader';

and then it uses the module in the following way:

const performancesResultsReader = new PerformancesResultsReader();
performancesResultsReader.read();

This file is called AppPage.component.tsx

The test file is located in the same folder and when I use the automatic mock, it works as expected. The automatic mock is implemented simply through the jest mock of the same import:

jest.mock('./../../models/PerformancesResultsReader');

In this way all the methods simply return undefined.

Now I was trying to add a manual mock instead of the automatic one.

This is the PerformancesResultsReader.js mock code:

console.log('including mock!');

const mock = jest.fn().mockImplementation(() => {
    return {
        read: () => {
            console.log('mocked');
        }
    };
});

export default mock;

I tried to place it inside a __mocks__ sub folder in the same level of the file I am testing, and I tried to put it also in the same folder of the imported module I want to mock. In both cases it doesn't seem to be called at all (the first console log never gets printed).

Any idea about what I am doing wrong please?

like image 395
quirimmo Avatar asked Mar 28 '18 11:03

quirimmo


1 Answers

I've found the way to make it work.

There are few steps needed in order to sort it out:

  1. When you're mocking your dependency, you can place your __mock__ folder or at the same level of the main file you're testing which imports it, or at the same level of the class you are going to mock
  2. In your unit tests file, the call to jest.mock must happen before you include your main file to be tested, the one which requires the file to be mocked

So, the code is the following.

Main file to be unit tested (AppPage.component.tsx):

// all imports
import PerformancesResultsReader from './../../models/PerformancesResultsReader'; // dependency to be mocked

// your AppPage component here
export default AppPage; 

Mock inside the __mock__ sub folder (PerformancesResultsReader.tsx):

class PerformancesResultsReader {
    constructor() {
        console.log('Mock constructor');
    }
    // all your methods here
}

export default PerformancesResultsReader;

And the final unit test (AppPage.component.spec.tsx):

// call the defined mock
jest.mock('./../../models/PerformancesResultsReader');
// import the main file which is going to be tested
import AppPage from './AppPage.component';

describe('App Container Component', () => {
    // your tests
});

The folders structure of the above example is the following:

- components
-- AppPage.component.tsx
-- AppPage.component.spec.tsx
- models
-- PerformancesResultsReader.tsx
-- __mock__
--- PerformancesResultsReader.tsx
like image 53
quirimmo Avatar answered Nov 10 '22 07:11

quirimmo