我正在尝试在 Jest 中模拟一个慢速网络(使用 React 测试库)。我试图设置的条件是这样的:
- UI 处于特定状态
- 异步 AJAX 请求被触发
- ui改变状态
- 异步请求完成
在我看来,这将是一个相当普遍的要求,因为使用异步编程,您必须了解在发送 AJAX 请求和完成请求之间可能发生的情况。但是,我根本找不到这方面的任何讨论或工具。
我正在尝试在 Jest 中模拟一个慢速网络(使用 React 测试库)。我试图设置的条件是这样的:
在我看来,这将是一个相当普遍的要求,因为使用异步编程,您必须了解在发送 AJAX 请求和完成请求之间可能发生的情况。但是,我根本找不到这方面的任何讨论或工具。
这个回复非常具体到 react-testing-libaray 但我认为这个概念是普遍适用的。
首先,我意识到如果您启动异步操作以响应用户事件(例如单击),那么您就没有问题 - 一旦您调用fireEvent.click
,您就处于状态 3,那么您可以使用waitFor()
等到你到达状态4。
其次,如果您的环境为您提供了异步操作承诺的句柄,那么您当然可以等待,这样您就没有问题了。
在我的例子中,异步操作是由一个计时器触发的,因为它在一个反应组件内,我从外部获得了该计时器的句柄。所以我的场景是这样的:
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 秒来运行。
希望这可以帮助其他尝试做类似事情的人。