В 7Geese мы используем Enzyme и Mocha для всех наших юнит-тестов React. Мы пользуемся им уже почти год, но сегодня я наткнулся на новую проблему, которая стала настоящей головной болью.
Взгляните на следующий произвольный компонент
class SomeComponent extends React.Component { static propTypes = { aProp: PropTypes.string.isRequired, anotherPropFunc: PropTypes.func.isRequired, }; handleClick = () => { // doStuff() assert.fail() } render() { return <ButtonComponent onClick={this.handleClick} /> } };
И простой тест на это
it('should fire handleClick when ButtonComponent is clicked', () => { const wrapper = shallow(<Component {...props} /> const stubbedEventHandler = sinon.stub(wrapper.instance(), 'handleClick'); chai.assert.isTrue(stubbedEventHandler.calledOnce); stubbedEventHandler.restore() });
Этот тест не сможет вызвать заглушенную версию handleClick и не пройдет тест. Теперь проверьте следующий очень похожий тест.
it('should fire handleClick when ButtonComponent is clicked', () => { const wrapper = shallow(<Component {...props} /> const stubbedEventHandler = sinon.stub(wrapper.instance(), 'handleClick'); this.setProps({aProp: 'string'}) chai.assert.isTrue(stubbedEventHandler.calledOnce); stubbedEventHandler.restore() }
Этот тест вызывает заглушенную версию handleClick, и тест проходит? Единственная разница заключается в изменении реквизита, но реквизит не имеет прямого влияния на этот метод. ЧТО ПРОИЗОШЛО? что это за вуду?
Оказывается, если вы заглушите свойство экземпляра компонента с неглубоким рендерингом, но компонент не нуждается в обновлении, т. Е. Его состояние или свойства не меняются, тогда ссылки на это свойство не обновляются в заглушке.
Обходной путь, который я нашел, заключается в использовании wrapper.instance().forceUpdate(), если вы не собираетесь изменять реквизиты или состояние перед вызовом заглушенного метода/свойства.
Надеюсь, эта статья поможет спасти чьи-то волосяные фолликулы.