jestjs - React 测试库清理在 Jest 的描述块中不起作用
问题描述
我有一些正在进行的测试,这是按预期工作的:
describe('Parent', () => {
afterEach(() => {
cleanup();
jest.resetModules();
});
describe('Test 1', () => {
const wrapper = render(
<MockProvider>
<MyComponent />
</MockProvider>,
);
test('1 ', () => {
expect(wrapper.baseElement).toMatchSnapshot();
expect(wrapper.getByText('Apply').disabled).toBe(true);
});
});
describe('Test 2', () => {
test('1 ', () => {
const wrapper = render(
<MockProvider>
<MyComponent />
</MockProvider>,
);
console.log(wrapper.getByText('Apply').disabled);
expect(1).toBe(1);
});
});
});
但是,当我将第二个渲染函数移出测试时,它会出错:
describe('Parent', () => {
afterEach(() => {
cleanup();
jest.resetModules();
});
describe('Test 1', () => {
const wrapper = render(
<MockProvider>
<MyComponent />
</MockProvider>,
);
test('1 ', () => {
expect(wrapper.baseElement).toMatchSnapshot();
expect(wrapper.getByText('Apply').disabled).toBe(true);
});
});
describe('Test 2', () => {
const wrapper = render(
<MockProvider>
<MyComponent />
</MockProvider>,
);
test('1 ', () => {
console.log(wrapper.getByText('Apply').disabled);
expect(1).toBe(1);
});
});
});
我得到的错误是
找到带有文本的多个元素:应用
我可以在控制台中看到组件被渲染了两次,所以我认为清理功能在描述块方面一定不能正常工作。这很奇怪,因为我们已经进行了 Enzyme 测试,并且设置和拆卸对这些都很好。
解决方案
为了理解这一点,我们需要了解一点关于如何Jest
运行我们的测试以及如何React Testing Library
渲染我们的组件。
笑话
考虑下面的代码并尝试猜测输出将是什么:
describe('First describe', () => {
console.log('First describe');
it('First test', () => {
console.log('First test');
});
});
describe('Second describe', () => {
console.log('Second describe');
it('Second test', () => {
console.log('Second test');
});
});
输出(悬停查看):
第一次描述
第二次描述
第一次测试
第二次测试
请注意,所有describe
方法都是在测试开始运行之前初始化的。
这应该已经让您对问题有所了解,但现在让我们看看 RTL。
反应测试库
考虑下面的代码并尝试猜测 DOM 在控制台中的外观:
const Greeting = () => 'Hello world';
describe('First describe', () => {
const wrapper = render(<Greeting />);
it('First test', () => {
console.log(wrapper.debug());
});
});
describe('Second describe', () => {
render(<Greeting />);
});
输出(悬停查看):
<body>
<div>Hello world</div>
<div>Hello world</div>
</body>
当我们没有为render
函数指定基本元素时,它总是使用相同的document.body
当我们不指定自定义容器时,<div>
元素包装由 RTL 添加。Hello world
默认情况下,所有 RTL 查询都绑定到基本元素document.body
——在这种情况下。
所以,
getByText('Hello world'); // will find two elements and throw
这就是RTL 中的代码在函数中的样子render
。(半伪代码)
if(!baseElement) {
baseElement = document.body // body will be shared across renders
}
if(!container) {
baseElement.appendChild(document.createElement('div')) // wraps our component
}
ReactDOM.render(component, container)
return { container, baseElement, ...getQueriesForElement(baseElement) }
为了解决这个问题
执行以下操作之一:
render
在it
ortest
方法中调用container
在查询中指定- 为每个指定不同的基本元素
render
推荐阅读
- javascript - 重新加载后如何刷新div
- node.js - Docker nodejs设置时区
- javascript - ChartJS 删除图表顶部的图例
- sql - SQL - 在 case when 语句中嵌套一个计数
- botframework - 创建 Teams Webhook“不支持统一组”?
- javascript - 具有多个端点的 Apollo 类型生成器 (codegen:generate)
- python - 根据 Python 中两列或多列的条件从上一行或下一行中获取值
- excel - 重新打开工作簿后 VBA 错误 13(类型不匹配)
- r - semi_join 根据多个 Y 列过滤 X 的列
- angular - 以角度处理多组件形式