如何使用 Jest、Enzyme for React-Native 在单元测试中模拟事件
我试图弄清楚如何在 React-Native 应用中使用 Jest 测试“onPress”事件,以确保调用正确的函数。
我查阅了文档和 Google,但在 React-Native 中找不到解决方案。
这是我发现的应该适用于带有
enzyme
的 React-Native 的内容:
const mockFunc = jest.fn();
const component = mount(<MyComponent onPress={mockFunc} />);
component.simulate('press');
expect(mockFunc).toHaveBeenCalled();
但这不起作用。似乎
mount
不起作用,我得到了这个输出:
ReferenceError: document is not defined
我尝试使用
shallow
,但当我查看函数的输出时,
TouchableOpacity
没有被渲染……而且你已经猜到了,它也不起作用。不知道该怎么办。
有人找到在 React-Native 上测试事件的方法吗?
谢谢
Enzyme 不支持 React-Native,因为它的渲染方式不同,并且不使用 DOM。这就是您收到错误
ReferenceError:文档未定义
的原因。您可以查看
此问题
以了解更多信息。React 团队目前正在努力在
react-test-renderer
中公开
.find()
方法来模拟组件上的操作。然后它应该适用于 React/React-native,而无需 DOM 环境。
您可以采取一种黑客手段(这就是我们在公司所做的),即渲染一个自定义组件,该组件扩展
TouchableOpacity
并映射
onClick
以调用
onPress
。类似这样的内容:
const mockPressable = (name) => {
const RealComponent = require.requireActual(name);
class Component extends RealComponent {
render() {
return React.createElement(
RealComponent.displayName || RealComponent.name,
{ ...this.props, onClick: this.props.onPress },
this.props.children
);
}
}
return Component;
};
jest.mock('TouchableOpacity', () => mockPressable('TouchableOpacity'));
并且在您的测试代码中,您调用
component.simulate('click')
。
这是一种黑客行为,我不确定这样做的后果是什么,但它对我们的用例有效。
您应该改用
shallow
,然后调用
.dive()
const mockFunc = jest.fn();
const component = shallow(<MyComponent onPress={mockFunc} />);
component.dive().simulate('press');
expect(mockFunc).toHaveBeenCalled();
我能够在 React Native 中运行您在问题中描述的测试。这是我的配置:
package.json
"scripts": {
...
"test": "node_modules/jest/bin/jest.js",
}
"devDependencies": {
...
"enzyme": "^3.1.0",
"enzyme-adapter-react-16": "^1.0.1",
"enzyme-to-json": "^3.1.2",
"jest": "^21.2.1",
"jest-enzyme": "^4.0.0",
"jest-expo": "~21.0.0",
}
"jest": {
"preset": "jest-expo",
"setupFiles": [
"./test/jestSetup.js"
],
"snapshotSerializers": [
"./node_modules/enzyme-to-json/serializer"
]
}
test/jestSetup.js
import { configure, shallow, render, mount } from 'enzyme'
import Adapter from 'enzyme-adapter-react-16'
configure( { adapter: new Adapter() } )
// enzyme
global.shallow = shallow
global.render = render
global.mount = mount
示例组件:
import React from 'react'
import { Button } from 'react-native'
const CancelButton = ( props ) =>
<Button
{ ...props }
onPress={ () => { props.navigation.goBack() } }
title="Cancel"
/>
export { CancelButton }
示例测试
import React from 'react'
import { CancelButton } from '../CancelButton'
test( 'onPress', () => {
const goBackFunc = jest.fn()
const navigation = {
goBack: goBackFunc,
}
const component = shallow(
<CancelButton
navigation={ navigation }
/>
)
component.simulate( 'press' )
expect( goBackFunc ).toHaveBeenCalled()
} )
.babelrc
{
"presets": ["babel-preset-expo"],
"env": {
"development": {
"plugins": ["transform-react-jsx-source"]
}
}
}