Jest – 如何模拟模块中的非默认导出



我试图从react-native中模拟NativeModules,但我找不到一种方法来只模拟该类,而不是整个react-native模块。

基本上,在我的生产代码中,我这样做:

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

在我的测试中,我想重写MyCustomNativeModule.目前,我发现的唯一方法是像这样模拟整个react-native模块:

// /__mocks__/react-native.js
module.exports = {
  NativeModules: {
    MyCustomNativeModule: {
      dismiss: () => {},
    },
  },
}

但这破坏了所有其他react-native功能。我看到人们经常使用像jest.mock('NativeModules', () => ... )这样的方法,但这似乎真的不起作用!

这是使用 jest.mock 手动模拟模块的解决方案react-native

为了简单起见,我模拟react-native模块。您可以使用真实react-native替换模拟的。

文件结构为:

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

模拟react-native模块:

react-native.ts

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

index.ts ,假设您在此文件中导入并使用react-native模块:

import { NativeModules } from './react-native';
export function main() {
  return NativeModules.MyCustomNativeModule.dismiss();
}

单元测试,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);
  });
});

100% 覆盖率的单元测试结果:

 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

以下是完成的演示: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/54393006

这个

呢:https://jestjs.io/docs/en/es6-class-mocks

.class

// sound-player.js
 export default class SoundPlayer {
   constructor() {
    this.foo = 'bar';
 }
  playSoundFile(fileName) {
   console.log('Playing sound file ' + fileName);
 }
}

用 jest.mock( ) 来嘲笑

import SoundPlayer from './sound-player';
const mockPlaySoundFile = jest.fn();
jest.mock('./sound-player', () => {
   return jest.fn().mockImplementation(() => {
       return {playSoundFile: mockPlaySoundFile};
    });
  });

更新

这种方式呢:

function mockFunctions() {
  const original = require.requireActual('../myModule');
  return {
    ...original, //Pass down all the exported objects
    test: jest.fn(() => {console.log('I didnt call the original')}),
    someFnIWantToCurry: {console.log('I will curry the original') return jest.fn((...args) => original.someFnIWantToCurry(...args)}),
  }
jest.mock('../myModule', () => mockFunctions());
const storage = require.requireMock('../myModule');

参见:https://github.com/facebook/jest/issues/936#issuecomment-265074320

相关内容

  • 没有找到相关文章

最新更新