使用 react-navigation 测试 onClick
testing onClick with react-navigation
我将 Jest 与 Enzyme 一起使用,我有这个组件,其中包括一个 navigate
方法调用:
export class LeadList extends React.Component {
render() {
const { navigate } = this.props.navigation;
return (
<List>
{this.props.data.allLeads.map((lead, i) => {
return (
<ListItem
key={i}
onPress={() =>
navigate('Details', lead.id)
}
/>
// ...
</ListItem>
)})}
</List>
);
}
}
我正在尝试测试它是否被正确调用,所以我把它放在一起:
const testProps = props => ({
data: {
allLeads: [
{id: 1, name: 'John Doe'},
{id: 2, name: 'Jane Doe'}
],
loading: false,
},
navigation: jest.fn((options, callback) => callback('Details', 1)),
...props,
})
describe('interactions', () => {
let props
let wrapper
beforeEach(() => {
props = testProps()
wrapper = shallow(<LeadList {...props} />)
})
describe('clicking a lead', () => {
beforeEach(() => {
wrapper.find(ListItem).first().prop('onPress')
})
it('should call the navigation callback', () => {
expect(props.navigation).toHaveBeenCalledTimes(1)
})
})
})
输出为:
Expected mock function to have been called one time, but it was called zero times.
处理这个问题的正确方法是什么?我需要使用间谍吗?
编辑:
当我这样改变它时,我得到了同样的结果:
const testProps = props => ({
// ...
navigation: {navigate: jest.fn()},
...props,
})
it('should call the navigation callback', () => {
expect(props.navigation.navigate).toHaveBeenCalledTimes(1)
})
输出:
expect(jest.fn()).toHaveBeenCalledTimes(1)
Expected mock function to have been called one time, but it was called zero times.
at Object.<anonymous> (__tests__/LeadList-test.js:48:35)
at tryCallTwo (node_modules/promise/lib/core.js:45:5)
at doResolve (node_modules/promise/lib/core.js:200:13)
at new Promise (node_modules/promise/lib/core.js:66:3)
at Promise.resolve.then.el (node_modules/p-map/index.js:46:16)
at tryCallOne (node_modules/promise/lib/core.js:37:12)
at node_modules/promise/lib/core.js:123:15
传递给组件的 prop navigation
不是一个函数。它是一个对象,包含一个名为 navigate
的函数。
具有讽刺意味的是,这正是您在组件代码中使用的内容:
const { navigate } = this.props.navigation;
因此,您必须将从测试中传递的导航道具更改为:
navigation: {navigate: jest.fn()}
然后在你的测试中:
expect(props.navigation.navigate).toHaveBeenCalledTimes(1)
编辑:
为了实际调用函数,您必须模拟压力机。现在代码找到了 onPress
函数,但没有调用它。
为此,您可以替换
wrapper.find(ListItem).first().prop('onPress')
和
wrapper.find(ListItem).first().props().onPress()
你需要一个间谍来测试这个。这是一个示例测试,用于在 LoginScreen
上找到 ForgotPassword
按钮并测试它是否导航到正确的屏幕。
test('Press Forgot Password Button', () => {
const spy = jest.spyOn(navigation, 'navigate')
const wrapper = shallow(
<LoginScreen
navigation={navigation}
error={{}}
onLogin={jest.fn()}
/>,
)
const forgotButton = wrapper.find('Button').at(0)
forgotButton.props().onPress()
expect(spy).toBeCalledWith('ForgotPassword')
})
我将 Jest 与 Enzyme 一起使用,我有这个组件,其中包括一个 navigate
方法调用:
export class LeadList extends React.Component {
render() {
const { navigate } = this.props.navigation;
return (
<List>
{this.props.data.allLeads.map((lead, i) => {
return (
<ListItem
key={i}
onPress={() =>
navigate('Details', lead.id)
}
/>
// ...
</ListItem>
)})}
</List>
);
}
}
我正在尝试测试它是否被正确调用,所以我把它放在一起:
const testProps = props => ({
data: {
allLeads: [
{id: 1, name: 'John Doe'},
{id: 2, name: 'Jane Doe'}
],
loading: false,
},
navigation: jest.fn((options, callback) => callback('Details', 1)),
...props,
})
describe('interactions', () => {
let props
let wrapper
beforeEach(() => {
props = testProps()
wrapper = shallow(<LeadList {...props} />)
})
describe('clicking a lead', () => {
beforeEach(() => {
wrapper.find(ListItem).first().prop('onPress')
})
it('should call the navigation callback', () => {
expect(props.navigation).toHaveBeenCalledTimes(1)
})
})
})
输出为:
Expected mock function to have been called one time, but it was called zero times.
处理这个问题的正确方法是什么?我需要使用间谍吗?
编辑:
当我这样改变它时,我得到了同样的结果:
const testProps = props => ({
// ...
navigation: {navigate: jest.fn()},
...props,
})
it('should call the navigation callback', () => {
expect(props.navigation.navigate).toHaveBeenCalledTimes(1)
})
输出:
expect(jest.fn()).toHaveBeenCalledTimes(1)
Expected mock function to have been called one time, but it was called zero times.
at Object.<anonymous> (__tests__/LeadList-test.js:48:35)
at tryCallTwo (node_modules/promise/lib/core.js:45:5)
at doResolve (node_modules/promise/lib/core.js:200:13)
at new Promise (node_modules/promise/lib/core.js:66:3)
at Promise.resolve.then.el (node_modules/p-map/index.js:46:16)
at tryCallOne (node_modules/promise/lib/core.js:37:12)
at node_modules/promise/lib/core.js:123:15
传递给组件的 prop navigation
不是一个函数。它是一个对象,包含一个名为 navigate
的函数。
具有讽刺意味的是,这正是您在组件代码中使用的内容:
const { navigate } = this.props.navigation;
因此,您必须将从测试中传递的导航道具更改为:
navigation: {navigate: jest.fn()}
然后在你的测试中:
expect(props.navigation.navigate).toHaveBeenCalledTimes(1)
编辑:
为了实际调用函数,您必须模拟压力机。现在代码找到了 onPress
函数,但没有调用它。
为此,您可以替换
wrapper.find(ListItem).first().prop('onPress')
和
wrapper.find(ListItem).first().props().onPress()
你需要一个间谍来测试这个。这是一个示例测试,用于在 LoginScreen
上找到 ForgotPassword
按钮并测试它是否导航到正确的屏幕。
test('Press Forgot Password Button', () => {
const spy = jest.spyOn(navigation, 'navigate')
const wrapper = shallow(
<LoginScreen
navigation={navigation}
error={{}}
onLogin={jest.fn()}
/>,
)
const forgotButton = wrapper.find('Button').at(0)
forgotButton.props().onPress()
expect(spy).toBeCalledWith('ForgotPassword')
})