我想Assert一个条件,我知道它不会立即为真,但在异步操作后可能为真,在这种情况下测试应该失败。
假设我正在测试这个计数器组件:
function Counter() {
const [value, setValue] = useState(1);
function decrement() {
if (value >= 0) { // <- off by one bug
someAsyncAction().then(() => setValue(value - 1));
}
}
return (
<>
Value is {value}
<button onClick={decrement}>Decrement</button>
</>
);
}
我可以编写此测试来检查值不应低于零:
const button = screen.getByRole("button", { name: "Decrement" });
expect(screen.getByText("Value is 1")).toBeInTheDocument();
userEvent.click(button);
expect(await screen.findByText("Value is 0")).toBeInTheDocument();
userEvent.click(button);
// !!! wrong !!!
expect(screen.getByText("Value is 0")).toBeInTheDocument();
expect(screen.queryByText("Value is -1")).not.toBeInTheDocument();
// !!! wrong !!!
但是最后两个Assert * 将始终通过 *,即使组件有一个bug,这意味着它将异步更新以显示“Value is-1”。
处理这种情况的建议方法是什么?
2条答案
按热度按时间62lalag41#
我想到的最好的办法是:
它尝试查找文本,等待超时(从默认的1秒减少到100毫秒,以加快测试速度),然后拒绝
expect
捕获的文本。如果文本 * 是 * 存在,则findByText
调用将解析,因此expect
将拒绝,测试将失败(不要忘记await
expect
)。此模式可以使用
waitFor
扩展到其他Assert:虽然这是可行的,但它有点复杂,特别是
waitFor
表单。我觉得这仍然可以改进,所以如果你有任何建议,请插话。eaf3rand2#
采用Tamlyn's excellent self-answer中提出的概念,我将其外推到一个名为
verifyNeverOccurs
的实用程序中,该实用程序与Testing Library的waitFor
具有相同的签名,但只有在您发送给它的回调Assert通过时才会失败:(This是在TypeScript中,但如果您希望在普通JS中使用,则可以随时剥离类型)。
示例用法: