如何在useEffect(func,[])的async api调用中使用setState钩子测试组件



我遇到了一个用react-native-testing-library进行组件单元测试的问题。

我有一个这样的组件:

// components/TestComponent.js
function TestComponent() {
const [data, setData] = useState();
useEffect(() => {
clientLibrary.getData()
.then((result) => { setData(result.data); } )
.catch((err) => { //handle error here } )
}, []);
render (
<ListComponent 
testID={"comp"} 
data={data})
renderItem={(item) => <ListItem testID={'item'} data={item} />}
/>
);
}

我像这样测试它:

// components/TestComponent.test.js
it('should render 10 list item', async () => {
const data = new Array(10).fill({}).map((v, idx) => ({
id: `v_${idx}`,
}));
const req = jest.spyOn(clientLibrary, 'getData').mockImplementation(() => {
return Promise.resolve(data);
});
const {queryByTestId, queryAllByTestId} = render(
<TestComponent />,
);
expect(await queryByTestId('comp')).toBeTruthy(); // this will pass
expect(await queryAllByTestId('item').length).toEqual(10); // this will fail with result: 0 expected: 10
}); // this failed

使用

测试将失败/通过Attempted to log "Warning: An update to TestComponent inside a test was not wrapped in act(...).指向useEffect中的setData

我试过用act()包装渲染,用act()断言,不嘲笑api调用,在act()包装整个测试,但错误不会消失。

对于这种情况,我已经尝试查看测试库文档/git/q&a,也搜索了stackoverflow问题,但我仍然不能使这个测试工作。

谁能告诉我解决这个问题的正确方向?

注:我不是要测试实现细节。我只是想测试给定一个获取结果X,该组件将按照预期呈现,即呈现10个列表项。

您的组件在useEffect内部安装期间执行异步状态更新,因此呈现行为具有异步副作用,需要封装在await act(async())调用中。请参阅关于数据获取的测试食谱文档。

您可以在测试中尝试这样做:

it('should render 10 list item', async () => {
// Get these from `screen` now instead of `render`
const { queryByTestId, queryAllByTestId } = screen
const data = new Array(10).fill({}).map((v, idx) => ({
id: `v_${idx}`,
}));
const req = jest.spyOn(clientLibrary, 'getData').mockImplementation(() => {
return Promise.resolve(data);
});
await act(async () => {
render(
<TestComponent />
);
})
expect(await queryByTestId('comp')).toBeTruthy();
expect(await queryAllByTestId('item').length).toEqual(10);
});

最新更新