Javascript 防止";不受法案(……)的约束。”;状态更新失败时发出Jest警告';不影响用户界面
我试图找出是否有一种方法可以防止Jest/测试库在导致警告发生的状态更新后没有任何可断言的内容时抛出“not wrapped in act(…)”警告,或者是否应该忽略此警告 假设我有一个简单的组件:Javascript 防止";不受法案(……)的约束。”;状态更新失败时发出Jest警告';不影响用户界面,javascript,reactjs,jestjs,react-testing-library,testing-library,Javascript,Reactjs,Jestjs,React Testing Library,Testing Library,我试图找出是否有一种方法可以防止Jest/测试库在导致警告发生的状态更新后没有任何可断言的内容时抛出“not wrapped in act(…)”警告,或者是否应该忽略此警告 假设我有一个简单的组件: import React, {useEffect, useState} from 'react'; import {getData} from 'services'; const MyComponent = () => { const [arr, setArr] = useState(
import React, {useEffect, useState} from 'react';
import {getData} from 'services';
const MyComponent = () => {
const [arr, setArr] = useState([]);
useEffect(() => {
(async () => {
const {items} = await getData();
setArr(items);
})();
}, []);
return (
<div>
{!(arr.length > 0) && <p>no array items</p>}
{arr.length > 0 && (
<ul>
{arr.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
)}
</div>
);
};
export default MyComponent;
此测试将通过,但我将得到“not wrapped in act(…)”警告,因为测试将在getData()
有机会完成之前完成
在本例中,来自getData()
的响应将arr
设置为与我最初在组件顶部设置的值相同的值(空数组)。因此,在异步函数完成后,我的UI不会改变——我仍然在看一段写着“无数组项”的文字——因此我没有任何可以断言的东西可以等待状态更新完成
我可以expect(getData).tohaveencalledtimes(1)
,但这并不需要等待函数调用后状态实际更新
我已尝试在测试中任意暂停,以便有时间执行setArr(items)
:
it('renders', async () => {
getData.mockResolvedValue({items: []});
render(<MyComponent />);
expect(screen.getByText('no array items')).toBeInTheDocument();
await new Promise(resolve => setTimeout(resolve, 2000));
expect(screen.getByText('no array items')).toBeInTheDocument();
});
it('renders',async()=>{
getData.mockResolvedValue({items:[]});
render();
expect(screen.getByText('no array items')).toBeInTheDocument();
等待新的承诺(resolve=>setTimeout(resolve,2000));
expect(screen.getByText('no array items')).toBeInTheDocument();
});
但这似乎没有什么帮助,老实说,我也不知道为什么
有没有办法通过只修改测试来处理这种情况?
我相信我可以通过重构MyComponent来解决这个问题,例如,将arr
作为一个道具传递给MyComponent,并将getData()
调用移动到父组件,或者创建一些仅用于测试的自定义道具,从而完全跳过getData()
调用,但我不想仅仅为了避免测试中的警告而修改组件
我使用的是v11.2.2。您可以使用
findByText
(getByText
和waitFor
的组合)来确保在断言解析时发生所有更新
it('renders',async()=>{
getData.mockResolvedValue({items:[]});
render();
expect(wait screen.findByText('no array items')).toBeInTheDocument();
});
谢谢。我知道findBy
并且已经大量使用了它,但我想我不知道它一定会等待状态更新。我提到的文档()使它看起来像是在等待异步DOM更改,但在这种情况下,DOM实际上没有更改(即使组件的呈现函数再次被调用),所以我想我认为这是行不通的。今后我必须记住这一点:)
it('renders', async () => {
getData.mockResolvedValue({items: []});
render(<MyComponent />);
expect(screen.getByText('no array items')).toBeInTheDocument();
await new Promise(resolve => setTimeout(resolve, 2000));
expect(screen.getByText('no array items')).toBeInTheDocument();
});