如何使用Jest和Enzyme对包含history.push的react事件处理程序进行单元测试?

时间:2018-06-04 14:18:55

标签: reactjs unit-testing jestjs enzyme html5-history

给出一个简单的组件:

export default class SearchForm extends Component {
  constructor(props) {
    super(props)
    this.state = { query: '' }
  }
  onSubmit = (event) => {
    event.preventDefault()
    history.push(`/results/${this.state.query}`, { query: this.state.query })
  }
  render() {
    return (
      <form onSubmit={this.onSubmit}>
        <input
          type="text"
          value={this.state.query}
          onChange={event => this.setState({ query: event.target.value })}
        />
        <button>Search</button>
      </form>
    )
  }
}

测试:

describe('SearchForm Component', () => {
  it('should navigate to results/query when submitted', () => {
    const wrapper = shallow(<SearchForm />)
    ...?
  })
})

如何验证表单提交是否将用户带到具有正确查询值的下一页?

我尝试过简单地模拟onSubmit处理程序并至少确认它已被调用,但这会导致history.push导致的安全性错误。

const wrapper = shallow(<SearchForm />)
const mockedEvent = { target: {}, preventDefault: () => {} }
const spy = jest.spyOn(wrapper.instance(), 'onSubmit')
wrapper.find('form').simulate('submit', mockedEvent)
expect(spy).toHaveBeenCalled()

2 个答案:

答案 0 :(得分:13)

它实际上很简单,你可以将任何道具传递给组件,当它在测试中浅层渲染时,就像那样:
const wrapper = shallow(<SearchForm history={historyMock} />)

顺便说一句,在onSubmit内,你应该像this.props.history.push(...)一样打电话。

现在,要创建一个模拟(documentation中的更多信息),您可以在测试中这样写:
const historyMock = { push: jest.fn() };

请记住,您实际上只是在模拟push对象的history方法,如果在组件中使用更多方法并想要测试它们,则应该为每个方法创建一个模拟测试。

然后,您需要断言已正确调用push模拟。要做到这一点,你要写下必要的断言:
expect(historyMock.push.mock.calls[0]).toEqual([ (url string), (state object) ]);
使用所需的(url string)(state object)来声明。

答案 1 :(得分:-1)

嘲笑它!

如果您创建文件夹__mocks__并向其添加模块历史记录,则可以覆盖其功能并检查它是否已被调用。