使用react-testing-library进行测试卸载

时间:2019-07-25 06:14:57

标签: reactjs react-testing-library react-test-renderer

我对何时/如何更新查询的元素感到困惑。例如:

我有一个计数按钮。当计数到3时,它消失了。

import React, { useState } from "react";

export default () => {
  const [count, setCount] = useState(0);

  return (
    <div>
      {count < 3 && (
        <button onClick={() => setCount(count + 1)}>{count}</button>
      )}
    </div>
  );
};

我正在像这样测试它:

test("Counter counts up and disappears", () => {
  const { queryByText } = render(<App" />);

  const button = queryByText("0");
  expect(button.textContent).toEqual("0");

  fireEvent.click(button);
  expect(button.textContent).toEqual("1");

  fireEvent.click(button);
  expect(button.textContent).toEqual("2");

  fireEvent.click(button);
  expect(button).toBe(null);
});

测试失败,并出现以下错误:

expect(received).toBe(expected)

Expected value to be (using ===):
  null
Received:
  <button>2</button>

为什么按钮元素知道其文本内容已更改?每次点击后,我们都不需要运行queryByText("1")queryByText("2")

为什么最后一次单击后不知道按钮已被卸载?而且,如果我们要检查它确实为空,则需要执行queryByText("3")

这是代码沙箱: https://codesandbox.io/s/react-testing-library-demo-76zhi

1 个答案:

答案 0 :(得分:1)

猜测是关于react-domjsdom(也用于测试)的工作方式。

(请纠正我或让我知道猜测是否可以接受!我将删除它。)

    queryByText返回的
  1. 按钮类型为HtmlElment

  2. reactreact-dom只是最小化了dom操作的任务,最终jsdom仍会完成文本更改和按钮删除工作。

  3. 由于测试工具正在使用jsdom,因此我检查了代码的removeChild部分,并相信they are following W3C specification。我假设在dom操作级别,jsdom会像浏览器一样工作。因此,我模拟了您的代码,如下所示:

const btn = document.getElementById('btn');
const btnContainer = document.getElementById('btnContainer');

btn.textContent = '1';
console.log('btn after click 1: ' + btn);
btn.textContent = '2';
console.log('btn after click 2: ' + btn);
btnContainer.removeChild(btn);
console.log('btn after removed: '+  btn);
<div id='btnContainer'><button id='btn'>0<button></div>

  1. 如您所见,从div中删除后,btn变量仍为[object HTMLButtonElement] 也许对包含一个已定义对象的数组使用splice类似于,初始obj仍然保持不变?

const obj = { 'a': 1};
const arr = [obj];
arr[0]['a'] = 2;
arr.splice(0, -1);
console.log(obj)


因此,我认为与how garbage collection works in javascript有关。

此外,也许不重用查询结果,并且在这种情况下始终再次查询,结果将更加可预期。


P.S。我发现有一个方法调用toBeInTheDocument