如何测试使用 Jest 导入自定义本机模块的 React Native 组件?
How to test a React Native component that imports a custom native module with Jest?
这是我尝试使用 React Native 0.39 和 Jest 18 测试的一个简单组件:
// index.ios.js
import React, { Component } from 'react';
import { AppRegistry, NativeModules, View } from 'react-native';
export default class TestProject extends Component {
componentDidMount() {
NativeModules.TestModule.test();
}
render() {
return <View style={{ flex: 1 }} />;
}
}
AppRegistry.registerComponent('TestProject', () => TestProject);
这是 TestModule 及其 test
方法:
// ios/TestProject/TestModule.m
#import "TestModule.h"
@implementation TestModule
RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(test){
NSLog(@"This is a test");
}
@end
以下测试失败并出现错误 TypeError: Cannot read property 'test' of undefined
:
// __tests__/index.ios.js
import 'react-native';
import renderer from 'react-test-renderer';
import React from 'react';
import Index from '../index.ios.js';
it('renders correctly', () => {
const tree = renderer.create(
<Index />
);
});
我已经阅读了关于如何 Mock native modules using jest.mock 的 Jest 文档,但我仍然不清楚如何扩展 Jest 的 NativeModules 模拟以包含我上面的 TestModule class。
Jest 是一个 JavaScript 测试工具,它不会 运行 您在本机模块中 Objective C/Swift/Java 编写的代码。您可以模拟本机模块的功能,以便您可以通过链接到的方法从 JavaScript 调用它。例如
jest.mock('NetInfo', () => {
return {
isConnected: {
fetch: () => {
return new Promise((accept, resolve) => {
accept(true);
})
}
}
}
});
您只需在本机模块所在的位置添加模拟即可:
import {
NativeModules,
} from 'react-native';
import React from 'react';
import renderer from 'react-test-renderer';
describe('TestProject', () => {
beforeEach(() => {
NativeModules.TestModule = { test: jest.fn() }
});
...
});
#__mocks__/react-native-modules
const ReactNative = require('react-native')
ReactNative.NativeModules = {
Defaults: {
RU: {
publicKey: '',
privateKey: '',
},
},
}
module.exports = ReactNative
然后
# in test file
jest.mock('react-native-modules')
import 'react-native-modules'
这样,你将嘲笑一次(在开玩笑之前)
jest.config.js
module.exports = {
preset: 'react-native',
setupFiles: ['./__mocks__/your-native-bridge.js']
};
__mocks__/your-native-bridge.js
import {NativeModules} from 'react-native';
NativeModules.YourNativeBridge = {
property: jest.fn()
};
不要忘记模拟 YourNativeBridge
中所有可能的函数和属性
这对我来说也失败了(react-native 0.57.5,jest 23.6.0)。我能够找到一个解决方案,但它与这里完全不同(在我的情况下,一个更优雅的修复)。
查看 the ticket I filed 了解更多详情。
本质上,我必须通过作为第二个参数传递给 jest.mock() and put this is in a script run at the beginning of each test using Jest's setupFiles 配置选项的函数来充实 NativeModules。
这是我尝试使用 React Native 0.39 和 Jest 18 测试的一个简单组件:
// index.ios.js
import React, { Component } from 'react';
import { AppRegistry, NativeModules, View } from 'react-native';
export default class TestProject extends Component {
componentDidMount() {
NativeModules.TestModule.test();
}
render() {
return <View style={{ flex: 1 }} />;
}
}
AppRegistry.registerComponent('TestProject', () => TestProject);
这是 TestModule 及其 test
方法:
// ios/TestProject/TestModule.m
#import "TestModule.h"
@implementation TestModule
RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(test){
NSLog(@"This is a test");
}
@end
以下测试失败并出现错误 TypeError: Cannot read property 'test' of undefined
:
// __tests__/index.ios.js
import 'react-native';
import renderer from 'react-test-renderer';
import React from 'react';
import Index from '../index.ios.js';
it('renders correctly', () => {
const tree = renderer.create(
<Index />
);
});
我已经阅读了关于如何 Mock native modules using jest.mock 的 Jest 文档,但我仍然不清楚如何扩展 Jest 的 NativeModules 模拟以包含我上面的 TestModule class。
Jest 是一个 JavaScript 测试工具,它不会 运行 您在本机模块中 Objective C/Swift/Java 编写的代码。您可以模拟本机模块的功能,以便您可以通过链接到的方法从 JavaScript 调用它。例如
jest.mock('NetInfo', () => {
return {
isConnected: {
fetch: () => {
return new Promise((accept, resolve) => {
accept(true);
})
}
}
}
});
您只需在本机模块所在的位置添加模拟即可:
import {
NativeModules,
} from 'react-native';
import React from 'react';
import renderer from 'react-test-renderer';
describe('TestProject', () => {
beforeEach(() => {
NativeModules.TestModule = { test: jest.fn() }
});
...
});
#__mocks__/react-native-modules
const ReactNative = require('react-native')
ReactNative.NativeModules = {
Defaults: {
RU: {
publicKey: '',
privateKey: '',
},
},
}
module.exports = ReactNative
然后
# in test file
jest.mock('react-native-modules')
import 'react-native-modules'
这样,你将嘲笑一次(在开玩笑之前)
jest.config.js
module.exports = {
preset: 'react-native',
setupFiles: ['./__mocks__/your-native-bridge.js']
};
__mocks__/your-native-bridge.js
import {NativeModules} from 'react-native';
NativeModules.YourNativeBridge = {
property: jest.fn()
};
不要忘记模拟 YourNativeBridge
这对我来说也失败了(react-native 0.57.5,jest 23.6.0)。我能够找到一个解决方案,但它与这里完全不同(在我的情况下,一个更优雅的修复)。
查看 the ticket I filed 了解更多详情。
本质上,我必须通过作为第二个参数传递给 jest.mock() and put this is in a script run at the beginning of each test using Jest's setupFiles 配置选项的函数来充实 NativeModules。