Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jest – How to mock non-default exports from modules?

I am trying to mock NativeModules from react-native, but I can't find a way to only mock that class, and not the entire react-native module.

Basically, in my production code I do this:

import { NativeModules } from 'react-native'
const { MyCustomNativeModule } = NativeModules

In my tests, I want to rewrite MyCustomNativeModule. At the moment the only way I have found is to mock the entire react-native module like this:

// /__mocks__/react-native.js

module.exports = {
  NativeModules: {
    MyCustomNativeModule: {
      dismiss: () => {},
    },
  },
}

But that breaks all the other react-native functions. I saw that often people use methods like jest.mock('NativeModules', () => ... ) but that really doesn't seem to be working!

like image 369
Guido Lodetti Avatar asked Jan 27 '19 21:01

Guido Lodetti


1 Answers

Here is the solution using jest.mock to mock react-native module manually.

In order to keep it simple, I simulate react-native module. You can use real react-native to replace the simulated one.

The file structure is:

.
├── index.spec.ts
├── index.ts
└── react-native.ts

Simulated react-native module:

react-native.ts:

const NativeModules = {
  MyCustomNativeModule: {
    dismiss: () => {
      // original implementation
      return 'real data';
    }
  }
};

export { NativeModules };

index.ts, assume you import and use react-native module in this file:

import { NativeModules } from './react-native';

export function main() {
  return NativeModules.MyCustomNativeModule.dismiss();
}

Unit test, index.spec.ts:

import { main } from './';
import { NativeModules } from './react-native';

jest.mock('./react-native', () => {
  return {
    NativeModules: {
      MyCustomNativeModule: {
        dismiss: jest.fn()
      }
    }
  };
});

describe('main', () => {
  it('should mock react-native correctly', () => {
    const mockedData = 'mocked data';
    (NativeModules.MyCustomNativeModule.dismiss as jest.MockedFunction<
      typeof NativeModules.MyCustomNativeModule.dismiss
    >).mockReturnValueOnce(mockedData);

    const actualValue = main();
    expect(actualValue).toBe(mockedData);
    expect(NativeModules.MyCustomNativeModule.dismiss).toBeCalledTimes(1);
  });
});

Unit test result with 100% coverage:

 PASS  src/stackoverflow/54393006/index.spec.ts
  main
    ✓ should mock react-native correctly (19ms)

----------|----------|----------|----------|----------|-------------------|
File      |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files |      100 |      100 |      100 |      100 |                   |
 index.ts |      100 |      100 |      100 |      100 |                   |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        5.096s

Here is the completed demo: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/54393006

like image 88
slideshowp2 Avatar answered Oct 12 '22 00:10

slideshowp2