在Jest中,使用setTimeout等待DOM操作是否正确?

问题描述

我有一个在按钮上注册click处理程序的函数。单击按钮后,变量NAME设置为输入元素的值。

当我尝试单击按钮并读取NAME变量时,expect()调用将返回派发NAME事件之前的sam click值。

这是我的代码(不起作用):

test("Input name and receive correctly",() => {
    document.body.innerHTML = `
    <input id="new-account-name">
    <button id="create-button">Create</button>
    `
    boot.boot(null);
    document.getElementById("new-account-name").value = "name";
    document.getElementById("create-button").click();
    expect(boot.NAME).toBe("name");
});

但是,如果我添加一个setTimeout()

setTimeout(()=>{
    expect(boot.NAME).toBe("name");
},50);

它有效并且测试通过。这是我应该怎么做吗?还是我的代码有问题?

解决方法

您永远都不想在单元测试中明确添加延迟,因为单元测试旨在尽快运行。如果行为明确与时间有关(例如,预定事件),则应尝试在实现中模拟时间,然后在测试中对其进行仿真。

在您的示例中,最好验证在触发单击按钮事件时调用名称值的设置函数(您可能必须模拟/监视)。 Jest提供了这种功能来验证函数是否被调用:

expect(mockFn).toBeCalledWith('name');

这样,您就知道事件是按您希望的方式处理的,并且还从实现(更改boot.Name字段的值)中分离了行为(以某种方式保留名称)。