带有 useEffect 的 Jest Act 警告
Posted
技术标签:
【中文标题】带有 useEffect 的 Jest Act 警告【英文标题】:Jest Act warning with useEffect 【发布时间】:2021-04-02 00:17:16 【问题描述】:我使用 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);
);
);
我的测试运行并通过了,但我继续收到一个动作警告,指出对状态的更新未包含在动作函数中。
我假设由于组件在加载时触发了 useEffect ,这正在改变渲染方法需要包装在一个动作块中的状态,但这样做:
act(() =>
const result: getByTestId , store = deepRender(
<ProductView />,
initialState: state );
fireEvent.click(getByTestId("add-to-cart-btn"));
)
不会消除警告,还会使结果中的存储对 act 块之外的断言不可用。有什么方法可以格式化它以减轻 act() 警告?
针对下面的一个问题,组件的useEffect是:
useEffect(() =>
if (something)
getDetails(something)
.then(getVariances)
.then(setProductVariances);
, []);
这使用 useState 设置 productVariances 状态值
【问题讨论】:
fireEvent
内部使用行为?
useEffect 是做什么的?给minimal reproducible example。
@jonrsharpe 在上面添加了一些细节
@evolutionxbox 那么这是否意味着将fireEvent
包装在一个动作块中是多余的?
那么getDetails
是什么?您是否将其替换为测试替身进行测试?再次,给minimal reproducible example。我怀疑一种解决方案是延迟模式,因此您可以控制何时(以及是否)解决或拒绝,正如我在例如github.com/textbook/starter-kit/blob/…
【参考方案1】:
您需要等待任何改变状态的副作用来解决,在这种情况下,我的方法是为组件提供一个处理此异步请求的服务的道具,并在我的测试中模拟,然后在模拟上“等待”服务来解决。
这是一个例子:
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
);
希望我过于简化的示例有所帮助,我很难找到解决方案
【讨论】:
【参考方案2】:您无需将render
包装在act
块中。你会收到一个行为警告,因为在承诺解决之后有一个状态更新,所以状态更新发生在一个行为块之外。我通常通过await
ing 解决这个问题,该承诺的解决方案在我的测试中触发了状态更新。
此外,您也不需要将 fireEvent
包装在 act 块中,因为它在内部使用 act。
【讨论】:
有趣。我想测试:`useEffect(() => storage.readObject('has_accepted_cookie').then((value) => setVisible(!value)) , [])`,我怎么能在这里等待?这对我来说似乎是不可能的。 您必须模拟出任何 storage.readObject ,以便您可以在测试中获得对其返回值的引用以上是关于带有 useEffect 的 Jest Act 警告的主要内容,如果未能解决你的问题,请参考以下文章
使用 useEffect 和 jest.useFakeTimers() 进行测试
使用 SetTimeout 测试自定义钩子,使用 Jest 测试 useEffect
如何使用 jest/enzyme 测试 useEffect 与 useDispatch 挂钩?