开玩笑地模拟和监视导入的异步函数 [英] Jest mock and spy on an imported async function
问题描述
我试图弄清楚如何在Jest中模拟导入的属性函数
I am trying to figure out how to mock an imported properties function in Jest
这是我的组件AboutScreen.js
import React from 'react';
import { Constants, WebBrowser } from 'expo';
import { View, Text } from 'react-native';
const AboutScreen = () => {
return (
<View>
<Text testId={"t-and-c"} onPress={() => WebBrowser.openBrowserAsync('tcUrl')}>
Terms & conditions
</Text>
</View>
);
};
export default AboutScreen;
我在AboutScreen.test.js中的测试如下所示
My test in AboutScreen.test.js looks like below
import React from 'react';
import { shallow } from 'enzyme';
import config from '../../config';
import AboutScreen from '../AboutScreen';
import { Constants, WebBrowser } from 'expo';
const { termsAndConditionsUrl, privacyPolicyUrl } = config;
jest.mock('expo', () => ({
Constants: {
manifest: {
version: '0.0.1',
releaseChannel: 'PROD',
},
WebBrowser: {
openBrowserAsync: jest.fn()
}
},
}));
it('click on terms and conditions link', () => {
const mock = jest.spyOn(WebBrowser, 'openBrowserAsync');
mock.mockImplementation(() => Promise.resolve());
// above statement return 'Cannot spyOn on a primitive value; undefined given'
// WebBrowser.openBrowserAsync = jest.fn(); --> This returns `WebBroser undefined
const wrapper = shallow(<AboutScreen />);
wrapper.find({ testId: 't-and-c' }).simulate('click');
expect(mock).lastCalledWith('abc');
// expect(WebBrowser.openBrowserAsync).toHaveBeenCalledWith('tcUrl);
});
我能够模拟Constants.manifest.version
,但无法弄清楚如何模拟'Browser`对象中的功能.
I was able to mock the Constants.manifest.version
but unable to figure out how to mock the function within the 'Browser` object.
推荐答案
您已经关闭.
您当前正在嘲笑WebBrowser
成为Constants
的属性内部,因此需要像这样将其移出:
You are currently mocking WebBrowser
to be a property inside of Constants
, so that needs to be moved out like this:
jest.mock('expo', () => ({
Constants: {
manifest: {
version: '0.0.1',
releaseChannel: 'PROD',
}
},
WebBrowser: {
openBrowserAsync: jest.fn()
}
}));
另一个问题是使用shallow
时simulate
的工作方式.在文档的常见问题部分:
The other issue is how simulate
works when using shallow
. From the Common Gotchas section of the doc:
即使名称暗示这将模拟一个实际事件,
.simulate()
实际上也将根据您提供的事件将组件的prop作为目标.例如,.simulate('click')
实际上将获得onClick
道具并调用它.
Even though the name would imply this simulates an actual event,
.simulate()
will in fact target the component's prop based on the event you give it. For example,.simulate('click')
will actually get theonClick
prop and call it.
...并且由于您的组件没有onClick
属性,因此调用.simulate('click')
最终无济于事.
...and since your component doesn't have an onClick
property calling .simulate('click')
ends up doing nothing.
这篇帖子建议直接调用道具,然后避免使用simulate
.
This post from an Airbnb dev recommends invoking props directly and avoiding simulate
.
您可以通过直接调用prop来调用onPress
,如下所示:
You can invoke onPress
by calling the prop directly like this:
wrapper.find({ testId: 't-and-c' }).props().onPress();
所有的工作测试看起来像这样:
So all together the working test looks like this:
import React from 'react';
import { shallow } from 'enzyme';
import config from '../../config';
import AboutScreen from '../AboutScreen';
import { Constants, WebBrowser } from 'expo';
const { termsAndConditionsUrl, privacyPolicyUrl } = config;
jest.mock('expo', () => ({
Constants: {
manifest: {
version: '0.0.1',
releaseChannel: 'PROD',
}
},
WebBrowser: {
openBrowserAsync: jest.fn()
}
}));
it('click on terms and conditions link', () => {
const mock = jest.spyOn(WebBrowser, 'openBrowserAsync');
mock.mockImplementation(() => Promise.resolve());
const wrapper = shallow(<AboutScreen />);
wrapper.find({ testId: 't-and-c' }).props().onPress();
expect(mock).toHaveBeenCalledWith('tcUrl'); // Success!
});
这篇关于开玩笑地模拟和监视导入的异步函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!