Jest vanilla JavaScript JSDOM 刷新失败,将 beforeAll 切换到 beforeEach 后第二次测试中断

问题描述 投票:0回答:2

我做了一个简单的测试来检查背景颜色是否发生变化

测试

/**
* @jest-environment jsdom
*/

const fs = require('fs');
const path = require('path');
const html = fs.readFileSync(path.resolve(__dirname, '../index.html'), 'utf8');
describe('Testing script.js', () => {
    let js
    beforeEach(()=>{
        document.documentElement.innerHTML = html.toString();
        js = require('../script');
    })
    afterEach(() => {
        document.documentElement.innerHTML = '';
    });
    test('Button click changes output content', () => {
        const myButton1 = document.getElementById('button-test1')
        const output = document.getElementById('output')
        const outputBefore = output.textContent
        myButton1.click()
        const outputAfter = output.textContent
        expect(outputBefore).not.toBe(outputAfter)
    });
    test('changes background colour', () => {
        const myButton2 = document.getElementById('button-test2')
        document.body.style.backgroundColor = 'blue'
        const bodyBefore = document.body.style.backgroundColor
        console.log(bodyBefore)
        myButton2.click()
        const bodyAfter = document.body.style.backgroundColor
        console.log(bodyAfter)
        expect(bodyBefore).not.toBe(bodyAfter)
    });

});

代码

const myButton1 = document.getElementById('button-test1')
const myButton2 = document.getElementById('button-test2')

myButton1.addEventListener('click', () => clickEvent1())
myButton2.addEventListener('click', () => clickEvent2())

function clickEvent1() {
    console.log("clickEvent1")
    const element = document.getElementById('output')
    if (element.textContent === "") element.textContent = "Hello World"
}

function clickEvent2() {
    console.log("clickEvent2")
    if (document.body.style.backgroundColor != 'red') document.body.style.backgroundColor = 'red'
}

结果

第二个测试失败,但是当单独运行时,测试工作正常。起初我认为这是因为同一个按钮被单击了两次,但这些是单独的元素。我不认为测试本身有问题,我无法解决。

我尝试过的:

我尝试使用 beforeEach/afterEach() 来拆解 html,希望在测试之间“重置”JSDOM。

我尝试过的事情

  • 更改测试顺序:第二个测试总是失败
  • 如果我删除第一个测试,它有效
  • 如果我删除 beforeEach 和 afterEach,返回到 beforeAll 它有效

这对我来说毫无意义,并且破坏了我对 Jest 工作原理的理解。

任何人都可以解释这种行为吗?

javascript unit-testing testing jestjs jsdom
2个回答
0
投票

问题

第二次测试中的单击事件未触发。

行为解释

当 Jest 通过 require 函数加载模块时,该模块会缓存在注册表中并执行。因此,第二次测试之前的 require('../script') 行不会加载或执行脚本,因为该模块已存在于注册表中。这意味着当您在第二次测试之前重置 DOM 时,最初注册的事件处理程序都不会附加到新 DOM 中的新元素。

您的问题有两种基本解决方案。

  1. 在测试之间重置模块。这将允许 require('../script') 行为每个测试独立加载和执行模块。

笑话文档: jest.resetModules()

在上面的示例代码中,一种可能的解决方案是删除 afterEach 代码块并更新 beforeEach 代码块。

beforeEach(() => {
    document.documentElement.innerHTML = html.toString();
    
    // Reset module registry
    jest.resetModules();

    js = require('../script');
});
  1. 不要在测试之间重置 DOM。这将允许您使用在测试之间持续存在的 DOM 的单个实例,并且首次加载和执行模块时应用的所有事件处理程序将对您的元素保持有效。

-1
投票

你不需要 afterEach,这会导致问题

© www.soinside.com 2019 - 2024. All rights reserved.