Jest - как смоделировать сетевую задержку - PullRequest
0 голосов
/ 17 апреля 2020

Я пытаюсь смоделировать медленную сеть в Jest (с помощью библиотеки тестирования React). Условие, которое я пытаюсь установить, выглядит примерно так:

  1. Интерфейс пользователя находится в заданном c состоянии
  2. asyn c AJAX запрос сработал
  3. пользовательский интерфейс изменяет состояние
  4. asyn c запрос завершается

Мне кажется, это было бы довольно распространенным требованием, потому что при асинхронном программировании вы должны знать о том, что могло произойти между отправкой запроса AJAX и его завершением. Тем не менее, я не могу найти какие-либо обсуждения или инструменты в этой области вообще.

1 Ответ

0 голосов
/ 21 апреля 2020

Этот ответ весьма специфичен c для реагирования-тестирования-библиотеки, но я думаю, что концепция в целом применима.

Прежде всего я понял, что если вы запустите операцию asyn c в ответ на пользовательское событие (скажем, щелчок), тогда у вас нет проблем - как только вы позвонили fireEvent.click, вы находитесь в состоянии 3, тогда вы можете использовать waitFor(), чтобы дождаться перехода в состояние 4.

Во-вторых, если ваша среда дает вам справку об обещании операции asyn c, тогда, конечно, вы можете просто подождать этого, чтобы снова у вас не возникло проблем.

В моем случае операция asyn c была запущена таймером, и, поскольку она находилась внутри реагирующего компонента, я получаю ручку для этого таймера извне. Итак, мой сценарий выглядит примерно так:

export default class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = { message: "initial" };
    }
    componentDidMount = () => setTimeout(async () => {
        this.setState({ message: "loading" });
        var message = await this.props.longRunningOperation();
        this.setState({ message });
    }, 5000);
    render = () => <div>{this.state.message}</div>
}

Состояние компонента изначально «начальное», через 5 секунд после его монтирования, оно запускает длительную операцию и устанавливает состояние «загрузка», затем, когда он получает ответ, он устанавливает состояние для текста этого ответа. Мой тестовый пример выглядит так:

test("long running response", async () => {
    const fakeLongRunningOperation = async () => new Promise(resolve =>
              setTimeout(() => resolve("success"), 2000));
    jest.useFakeTimers();
    var app = render(<App longRunningOperation={fakeLongRunningOperation} />);
    jest.advanceTimersByTime(4000)
    expect(app.queryByText("initial")).not.toBeNull();
    jest.advanceTimersByTime(2000)
    expect(app.queryByText("loading")).not.toBeNull();
    jest.advanceTimersByTime(2000)
    await waitFor(() => { expect(app.queryByText("success")).not.toBeNull() });
});

Мы подделываем длительную операцию с функцией, которая возвращает «успех» после 2-секундной задержки. Через 4 секунды мы ожидаем, что состояние все еще будет «начальным», затем еще через 2 секунды мы ожидаем, что оно «загружается», и еще через 2 секунды мы ожидаем, что оно будет «успешным». И мы используем фальшивые таймеры, чтобы на самом деле тест не занимал 8 секунд.

Надеюсь, что это поможет любому, кто пытается сделать нечто подобное.

...