简体   繁体   English

带有 useEffect 的 Jest Act 警告

[英]Jest Act warning with useEffect

I have Jest set up using react-testing-library and I have a test written as so:我已经使用 react-testing-library 设置了 Jest,并且我有一个这样编写的测试:

describe("Some Functionality", () => {
it("Should add a given product to the cart state", async () => {
    const state = getMockState();
    
    const { result: { getByTestId }, store } = deepRender(
        <ProductView />,
        { initialState: state });

    act(() => {
        fireEvent.click(getByTestId("add-to-cart-btn"));
    })

    const newState = store.getState() as RootState;
    expect(someassertion);
});
});

My test runs and passes but I continue to get an act warning that an update to the state wasn't wrapped in an act function.我的测试运行并通过,但我继续收到一个警告,即 state 的更新未包含在 function 中。

I assume since the component has a useEffect firing on load that is changing the state that the render method needs to be wrapped in an act block also but doing this:我假设由于组件在加载时触发了 useEffect ,它正在改变 state ,因此渲染方法也需要包装在一个动作块中,但这样做:

    act(() => {
        const { result: { getByTestId }, store } = deepRender(
             <ProductView />,
             { initialState: state });

        fireEvent.click(getByTestId("add-to-cart-btn"));
    })

Doesn't get rid of the warnings and also makes the store from the result unavailable to the assertions outside the act block.不会消除警告,并且还会使结果中的存储对 act 块之外的断言不可用。 Is there any way to format this to mitigate the act() warnings?有没有办法格式化它以减轻 act() 警告?

in response to a question below, the component's useEffect is:针对以下问题,组件的 useEffect 为:

useEffect(() => {
    if (something) {
        getDetails(something)
        .then(getVariances)
        .then(setProductVariances);
    }
}, []);

This sets a productVariances state value using useState这使用 useState 设置 productVariances state 值

You don't need to wrap render in an act block.您不需要将render包装在act块中。 You're getting an act warning because there is a state update after the resolution of a promise and so that state update happens outside of an act block.您会收到行为警告,因为在解决 promise 之后存在 state 更新,因此 state 更新发生在行为块之外。 I've generally gotten around this by await ing on the same promise whose resolution is triggering a state update in my test.我通常通过在我的测试中触发await更新的同一个 promise 来解决这个问题。

Also, you don't need to wrap fireEvent in an act block either because it uses act internally.此外,您也不需要将fireEvent包装在 act 块中,因为它在内部使用 act。

You need to wait for any sideeffects that change the state to resolve, my approach in this cases is to give the component a prop for the service that handles this async request and mock in my test, then "await" on the mock service to resolve.您需要等待任何改变 state 的副作用来解决,在这种情况下,我的方法是为组件提供处理此异步请求并在我的测试中模拟的服务的道具,然后在模拟服务上“等待”以解决.

Heres an example:这是一个例子:

it('renders when empty list of smartfields is passed', async () => {
    const rendered = render(
        <SomeComponent
          someprop={'321'}
          someotherprop={'123'}
          serviceProp={yourServiceMocked}
        />
    );
    // here you would make assertions on your "loading" state
    
    // HERE you await for you promise to resolve
    await act(() => yourServiceMocked);
    
    // here you would make assertions when your state has solved the promise
  });

Hope my oversimplified example helps, I had a hard time finding the solution for this希望我过于简化的示例有所帮助,我很难找到解决方案

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM