Рассмотрим следующий упрощенный компонент React. Когда вы нажимаете кнопку, он вызывает API-интерфейс к внешнему URL-адресу.
- Если он успешен, он увеличивает счетчик
- Если он неудачен, он уменьшает счетчик
import axios from 'axios';
import PropTypes from 'prop-types';
import React from 'react';
class MyCoolButton extends React.Component {
static propTypes = {
initialCounter: PropTypes.number.isRequired
};
constructor(props) {
super(props);
this.onClick = this.onClick.bind(this);
this.state = {
counter: props.initialCounter
}
}
onClick() {
const url = `/some/url/here`;
const data = { foo: 'bar' };
const config = { headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' } };
const { counter } = this.state;
return axios.patch(url, data, config)
.then((response) => { /* Success! */ this.setState({ counter: counter + 1 }); })
.catch((error) => { /* Failure :( */ this.setState({ counter: counter - 1 }); });
}
render() {
return (
<div className="container">
<span>Counter value is: {this.state.counter}</span>
<input className="cool-button" type="button" onClick={this.onClick} />
</div>
);
}
}
export default MyCoolButton;
Я хотел написать тестовый пример с использованием Jest, чтобы убедиться, что в случае сбоя мы правильно уменьшаем кнопку.
Я попробовал следующее:
describe('an error occurred while updating', () => {
beforeEach(() => {
axios.patch.mockImplementationOnce(() => Promise.reject('boo'));
});
it('decrements the counter', async() => {
// NOTE: The below uses Enzyme and Chai expectation helpers
wrapper = mount(<MyCoolButton initialCounter={99} />);
// Click the button
wrapper.find(`.cool-button`).first().simulate('click');
// Check for decrmented value
const body = wrapper.find('.container span');
expect(body).to.have.text('Counter value is: 98');
});
});
Проблема заключается в том, что щелчок и последующее обновление state
выполняются асинхронно, поэтому мы проверяем на наличие сбоев, прежде чем он сможет даже обновить компонент с ошибкой.
Многие примеры в Интернете, похоже, подсказывают async
/ await
, что я не очень хорошо понимаю. Похоже, что await
принимает Promise
в качестве аргумента, но в моем случае я имитирую щелчок, который дополнительно вызывает обработчик, который возвращает Promise
, поэтому я не могу await
на этом топоре ios Promise
для непосредственного завершения.
Какова лучшая практика тестирования здесь?
Спасибо!