我正在为React应用程序编写一个集成测试,也就是一个将多个组件一起测试的测试,我想模拟对外部服务的任何调用.

问题是,测试似乎在异步回调执行之前执行,导致测试失败.

这有什么关系吗?我是否可以等待调用异步代码完成?

下面是一些糟糕的pseudo代码来说明我的观点.

我想测试一下,当我挂载Parent时,它的子组件会呈现从外部服务返回的内容,我将对此进行模拟.

class Parent extends component
{
     render ()
     {
         <div>
            <Child />
         </div>
     }
}
class Child extends component
{
     DoStuff()
     {
         aThingThatReturnsAPromise().then((result) => {
           Store.Result = result
         })
     }

    render()
    {
       DoStuff()
       return(<div>{Store.Result}</div>)


    }
}
function aThingThatReturnsAPromise()
{
     return new Promise(resolve =>{
          eternalService.doSomething(function callback(result) {
               resolve(result)
          }
    }

}

当我在测试中这样做时,它失败了,因为它在回调被触发之前被执行.

jest.mock('eternalService', () => {
    return jest.fn(() => {
        return { doSomething: jest.fn((cb) => cb('fakeReturnValue');
    });
});

describe('When rendering Parent', () => {
    var parent;

    beforeAll(() => {
        parent = mount(<Parent />)
    });

    it('should display Child with response of the service', () => {
        expect(parent.html()).toMatch('fakeReturnValue')
    });
});

我如何测试这个?我知道angular可以用zonejs解决这个问题,在React中有没有等效的方法?

推荐答案

Updated for Jest 27+

对于jest 27+,您还可以使用process.下一步:

await new Promise(process.nextTick);

(感谢阿德里安·戈东的 comments )

Original Answer

下面是一段等待未决promise 得到解决的片段:

const flushPromises = () => new Promise(setImmediate);

请注意,setImmediate是一种非标准功能(预计不会成为标准).但是,如果它对您的测试环境足够,那么它应该是一个好的解决方案.其描述:

此方法用于中断长时间运行的操作,并在浏览器完成其他操作(如事件和显示更新)后立即运行回调函数.

下面是使用async/await的大致用法:

it('is an example using flushPromises', async () => {
    const wrapper = mount(<App/>);
    await flushPromises();
    wrapper.update(); // In my experience, Enzyme didn't always facilitate component updates based on state changes resulting from Promises -- hence this forced re-render

    // make assertions 
});

如果你想要一些实际工作的例子,我经常使用这个.

Reactjs相关问答推荐

面对动画警告:未指定`useNativeDriver`.这是必需的选项,并且必须在REACT本机中显式设置为`true`或`False`

TanStack/Reaction-Query在我的Vercel应用程序中不起作用

React useContext 的未定义返回值

为什么 useEffect 的初始化对于加载 localStorage 不起作用?

从ReactDataGridtry 将数据传递给父组件

如何根据用户在react.js中的 Select , Select 多个心形图标?

这个简单的React组件为什么会多次渲染?

无法从子组件传递数据到父组件

React 组件列表中的第一个计时器正在获取值 NaN

图像路径很奇怪,部署 Next.js 应用程序后我看不到任何图像

如何在不重新加载页面的情况下加载新添加的数据?

React JS:如何判断用户使用的是浏览器 url 还是桌面 electron

React Router 6.4CreateBrowserRouter子元素不显示

谁能根据经验提供有关 useEffect 挂钩的更多信息

react-markdown 不渲染 Markdown

模块解析失败:意外令牌 (257:106) 您可能需要适当的加载程序来处理此文件类型

当状态改变时如何执行一些动作,但只针对第一次更新?

如何使用 babel 将 SVG 转换为 React 组件?

找不到元素 - 这是参考问题吗?

为什么我从另一个组件收到错误?