首页 > 解决方案 > 当我正在测试的文件通过从卸载的 DOM 中抓取一个元素开始时,我如何在 Jest 中运行测试?

问题描述

我是测试和开玩笑的新手。我正在尝试在 app6.test.js 中运行测试。这是我的第一个。

期望是我的测试在正确运行后通过或失败。目前,它正在失败。我有信心知道为什么。我会在几秒钟内解决这个问题。

这是测试失败时我得到的错误:

FAIL  maze/app6.test.js
  ● Test suite failed to run

    TypeError: Cannot read property 'style' of null

       6 | const yRows = height / cube;
       7 | const cols = width / cube;
    >  8 | maze.style.width = width + 'px';
         |      ^
       9 | maze.style.height = height + 'px';
      10 | 
      11 | const trees = [];

      at Object.<anonymous> (maze/app6.js:8:6)
      at Object.<anonymous> (maze/app6.test.js:7:37)

Test Suites: 1 failed, 1 total

所以,我相信它失败了,因为据我了解,Jest 进入包含待测试代码的文件,并尝试运行该文件。但在我的情况下,它不能这样做,因为我的文件试图加载一个 DOM 元素,并且任何浏览器都没有加载 DOM。

我最接近解决方案的方法是尝试打开使用 Puppeteer 运行脚本的网页,然后运行该函数:

/**
 * @jest-environment jsdom
 */

const puppeteer = require("puppeteer")

const { checkIfCellsAreAdjacent } = require("./app6");

test("should output true or false", async () => {
    const browser = await puppeteer.launch({
        headless: false,
    })

    const page = await browser.newPage();
    await page.goto(`C:\\Users\\myName\\2020-Coding-Projects\\mentoring\\kruskel\\maze\\maze-4.html`)
    const boolean = checkIfCellsAreAdjacent({ x: 29, y: 30 }, { x: 30, y: 30 });
    expect(boolean).toBe(true);
});

但无论我在那里做什么,它都没有奏效。

现在,我可以通过 app6.js 并通过外科手术删除所说的行 let maze = document.getElementById('maze');以及之后引用它的所有内容。但这需要通过大量我宁愿保持集成的代码。必须有替代方案。

回复:研究,我去过大约 6-7 个不同的网站,通过谷歌搜索“开玩笑的 typeerror 无法读取 null 的属性 'style'”。这些链接谈论,eeeh,不是特别相似的问题(尽管它们至少使用相同的语言)。他们把我引向了“嘲笑”一个元素的概念,但显然我没有正确地做到这一点......

帮助!谢谢,麻烦您了。

编辑:所以没有人要问... app6.js 的前 8 行:

let maze = document.getElementById('maze');
const height = 900;
const width = 1500;
const cube = 50 // cell size = 20px by 20px. Hence cube
const yRows = height / cube;
const cols = width / cube;
maze.style.width = width + 'px';

标签: javascriptunit-testingjestjs

解决方案


Jest DOM 和 Puppeteer 测试是正交的。如果是被测试的实现,所有涉及到puppeteer的都不属于这个测试。

看来 app6.js 的问题在于它访问顶层的 DOM 而不是需要它的函数,这需要在导入模块之前设置模拟,因此需要在测试中导入它而不是在顶层等级。jest.isolateModules或 和 的组合require适用jest.resetModules于在不干扰其他测试的情况下测试模块。

maze需要通过模拟document.getElementById调用或将其放入 DOM 来模拟元素。前一个选项需要在测试后重置模拟;最好始终使用restoreMocks配置选项来完成此操作。后者需要在测试后进行清理:

let maze;
let app6;

beforeEach(() => {
  maze = document.createElement('div');
  maze.setAttribute('id', 'maze');
  document.body.appendChild(maze);

  jest.isolateModules(() => {
     app6 = require('./app6');
  });
});

test("should output true or false", () => {
    const boolean = app6.checkIfCellsAreAdjacent({ x: 29, y: 30 }, { x: 30, y: 30 });
    expect(boolean).toBe(true);
});

afterEach(() => {
  document.body.removeChild(maze);
});

推荐阅读