使用react-navigation测试onClick

时间:2017-12-13 20:47:35

标签: reactjs react-native jestjs react-navigation enzyme

我正在使用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

2 个答案:

答案 0 :(得分:4)

你需要一个间谍来测试这个。以下是在ForgotPassword上查找LoginScreen按钮并测试其导航到正确屏幕的示例测试。

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')
})

答案 1 :(得分:2)

传递给组件的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()