Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs 如何在内部使用异步函数和setState测试useEffect_Reactjs_Axios_Jestjs_React Hooks_React Testing Library - Fatal编程技术网

Reactjs 如何在内部使用异步函数和setState测试useEffect

Reactjs 如何在内部使用异步函数和setState测试useEffect,reactjs,axios,jestjs,react-hooks,react-testing-library,Reactjs,Axios,Jestjs,React Hooks,React Testing Library,我已经建立了一个github项目,以了解如何更好地测试react(v16.8.0)useEffect钩子。 我在useEffect中调用api获取数据,并将接收到的数据设置为状态组件元素。 我的组件将查询作为道具接收,如果查询道具字符串不为空,则进行api调用。我想用一个no-empty查询prop来测试api调用是否成功,组件是否正确设置了状态 我知道测试useEffect所面临的问题是,与useEffect相关的效果不会阻止浏览器更新屏幕,因此测试会在useEffect正常工作之前结束。 我

我已经建立了一个github项目,以了解如何更好地测试react(v16.8.0)useEffect钩子。 我在useEffect中调用api获取数据,并将接收到的数据设置为状态组件元素。 我的组件将查询作为道具接收,如果查询道具字符串不为空,则进行api调用。我想用一个no-empty查询prop来测试api调用是否成功,组件是否正确设置了状态

我知道测试useEffect所面临的问题是,与useEffect相关的效果不会阻止浏览器更新屏幕,因此测试会在useEffect正常工作之前结束。 我从React文档中了解到,React test utils中有一个名为act的API,用于包装呈现组件并对其执行更新的代码。 即使我尝试使用它,我的代码仍然会有同样的问题

这是我正在尝试测试的组件:

constdisplaydata=({query,onQueryChange})=>{
const[data,setData]=useState({hits:[]});
useffect(()=>{
const fetchData=async()=>{
const result=等待axios.get(
`http://hn.algolia.com/api/v1/search?query=${query}`,
);
setData(result.data);
};
如果(!!查询)fetchData();
},[查询];
返回(
    {data.hits.map(项=>(
  • ))}
); };
这是我为它写的测试:

it(“设置查询时应显示新条目”,()=>{
const el=document.createElement(“div”);
文件.正文.附件(el);
mockResolvedValue({data:{hits:FAKE_hits}});
行动(()=>{
渲染(,el);
});
const liCounts=el.queryselectoral(“li”);
expect(li计数长度).toBe(2);
});
我一直收到一个警告告诉我

对测试内部DisplayData的更新未包装在act(…)中

我的测试失败了,因为收到的liCounts是0,而不是预期的2

插入相同的控制台消息来调试应用程序,我相信问题在于useEffect是在测试执行之后启动的,但我不知道如何继续

更新
感谢@jornsharpe,我使用React版本16.9.0-alpha.0解决了我的问题,该版本具有act api的异步版本。

以下是单元测试解决方案:

我们使用
jest.spyOn(axios,'get')
模拟
axios.get
方法及其解析/拒绝的值,而不影响实际网络。这允许我们的单元测试在没有副作用的环境中运行,并且与系统环境、网络环境等隔离

我们使用helper来确保获取的数据和UI已经更新

编写UI测试时,渲染、用户事件或数据获取等任务可以被视为与用户界面交互的“单元”。react-dom/test-utils提供了一个名为act()的帮助程序,确保在做出任何断言之前,已处理并应用了与这些“单元”相关的所有更新:

最后,我们断言是否调用了
axios.get
方法,并通过快照测试断言
data
是否正确呈现

index.tsx

import React,{useState,useffect}来自“React”;
从“axios”导入axios;
export const DisplayData=({query,onQueryChange})=>{
const[data,setData]=useState

))}

);
};
index.spec.tsx

从“React”导入React;
从“/”导入{DisplayData};
从“axios”导入axios;
从“react test renderer”导入渲染器,{act};
描述('DisplayData',()=>{
它('设置查询时应显示新条目',async()=>{
常数mProps={
查询:“pippo”,
onQueryChange:jest.fn()
};
const FAKE_HITS=[{objectID:1,url:'haha.com',title:'haha'}];
const axiosGetSpy=jest.spyOn(axios,'get').mockResolvedValueOnce({data:{hits:FAKE_hits}});
let组件;
等待动作(异步()=>{
component=renderer.create();
});
expect(axiosGetSpy).toBeCalledWith('http://hn.algolia.com/api/v1/search?query=pippo');
expect(component.toJSON()).toMatchSnapshot();
axiosGetSpy.mockRestore();
});
它('查询为空字符串时不应获取数据',异步()=>{
常数mProps={
查询:“”,
onQueryChange:jest.fn()
};
const axiosGetSpy=jest.spyOn(axios,'get');
let组件;
等待动作(异步()=>{
component=renderer.create();
});
expect(axiosGetSpy).not.toBeCalled();
expect(component.toJSON()).toMatchSnapshot();
axiosGetSpy.mockRestore();
});
});
100%覆盖率的单元测试结果:

PASS src/stackoverflow/56410688/index.spec.tsx
显示数据
✓ 设置查询时应显示新条目(28毫秒)
✓ 查询为空字符串时不应获取数据(5ms)
-----------|----------|----------|----------|----------|-------------------|
文件|%Stmts |%Branch |%Funcs |%Line |未覆盖行|s|
-----------|----------|----------|----------|----------|-------------------|
所有文件| 100 | 100 | 100 | 100 ||
index.tsx | 100 | 100 | 100 | 100 ||
-----------|----------|----------|----------|----------|-------------------|
测试套件:1个通过,共1个
测试:2次通过,共2次
快照:2个通过,共2个
时间:3.666秒
index.spec.tsx.snap

// Jest Snapshot v1, 

exports[`DisplayData should not fetch data when query is empty string 1`] = `<ul />`;

exports[`DisplayData should show new entries when query is set 1`] = `
<ul>
  <li>
    <a
      href="haha.com"
    >
      haha
    </a>
  </li>
</ul>
`;

源代码:

请参阅@jornsharpe,非常感谢您再次关注16.9.0-alpha.0版本。我已经试过了,但仍然在使用rea的渲染api