我试图从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