Vanilla JS应用中Testing Library fireEvent.click()测试无效问题
问题:Jest+Testing Library点击事件测试不通过,DOM数值未递增
手动点击按钮时,.output元素的数值正常递增,但使用fireEvent.click()触发点击后,DOM中的数值未更新,导致测试失败。
相关代码
main.js
const incrementBtn = document.querySelector(".increment"); const outputElement = document.querySelector(".output"); let counter = Number(outputElement.textContent); function increment() { outputElement.textContent = counter++; } incrementBtn.addEventListener("click", increment);
main.test.js
import { fireEvent } from "@testing-library/dom"; ... describe("index.html", () => { beforeEach(() => { dom = new JSDOM(html, { runScripts: "dangerously" }); container = dom.window.document.body; }); // 测试通过 it("renders a heading element", () => { expect(container.querySelector("h3")).not.toBeNull(); }); // 测试不通过 it("increment a value via JavaScript when the button is clicked", async () => { const button = container.querySelector(".increment"); fireEvent.click(button); // 触发事件 expect(container.querySelector(".output")).toHaveTextContent("1"); // 测试失败 }); });
index.html
<!DOCTYPE html> <html lang="en"> <body> <div class="wrapper"> <h3>Counter App</h3> <p>The Count is:</p> <p class="output">0</p> <div class="buttons"> <button class="increment"> <svg class="icon icon-plus"><use xlink:href="#icon-plus"></use></svg> </button> </div> </div> <svg> <defs> <symbol id="icon-plus" viewBox="0 0 32 32"> <path d="M31 12h-11v-11c0-0.552-0.448-1-1-1h-6c-0.552 0-1 0.448-1 1v11h-11c-0.552 0-1 0.448-1 1v6c0 0.552 0.448 1 1 1h11v11c0 0.552 0.448 1 1 1h6c0.552 0 1-0.448 1-1v-11h11c0.552 0 1-0.448 1-1v-6c0-0.552-0.448-1-1-1z" ></path> </symbol> </defs> </svg> <script src="main.js"></script> </body> </html>
测试报错信息
● index.html › increment a value via JavaScript when the button is clicked expect(element).toHaveTextContent() Expected element to have text content: 1 Received: 0 22 | fireEvent.click(button); 23 | > 24 | expect(container.querySelector(".output")).toHaveTextContent("1"); | ^ 25 | }); 26 | }); 27 | at toHaveTextContent (main.test.js:24:48) at tryCatch (main.test.js:2:1) at Generator.<anonymous> (main.test.js:2:1) at Generator.next (main.test.js:2:1) at asyncGeneratorStep (main.test.js:2:1) at _next (main.test.js:2:1) at main.test.js:2:1 at Object.<anonymous> (main.test.js:2:1) Test Suites: 1 failed, 1 total Tests: 1 failed, 1 passed, 2 total Snapshots: 0 total Time: 4.199 s
问题原因及解决方法
原因
问题出在counter++的执行顺序:counter++是后自增运算符,会先返回counter当前的值,再将counter加1。第一次点击时,outputElement.textContent被设置为初始值0,之后counter才变成1,导致DOM显示的数值不符合测试预期。
手动点击时看似正常,是因为用户不会即时校验DOM的瞬间变化,第二次点击时数值会更新为1,但测试是检查第一次点击后的结果,因此暴露了这个逻辑问题。
解决方法
将counter++改为前自增运算符++counter,先完成counter的递增,再将更新后的值赋值给DOM元素:
function increment() { outputElement.textContent = ++counter; }
或者先更新counter再赋值,逻辑更直观:
function increment() { counter += 1; outputElement.textContent = counter; }
修改后,第一次点击按钮后.output元素的内容会直接变为1,测试即可通过。
内容的提问来源于stack exchange,提问作者Stanley Ulili
相关产品推荐
相关产品推荐

