在 Jest 中异步测试 React Navigation 5:NavigationContainer 导致控制台错误

Mar*_*ram 6 reactjs jestjs react-native react-navigation react-navigation-v5

我正在使用react-native-testing-libraryreact-navigation从 4升级到 5 后,我按照以下说明进行操作:https : //callstack.github.io/react-native-testing-library/docs/react-navigation升级了我的大部分测试套件。

到现在为止还挺好。这里的关键基本上是将您的测试包装在一个中,NavigationContainer以便我的组件可以访问以前来自react-navigation-hooks.

当我的测试是同步的时,这很好用,但是一旦我将async关键字添加到测试函数中,我就会收到以下警告:

console.error
    Warning: An update to ForwardRef(NavigationContainer) inside a test was not wrapped in act(...).

    When testing, code that causes React state updates should be wrapped into act(...):

    act(() => {
      /* fire events that update state */
    });
    /* assert on the output */

    This ensures that you're testing the behavior the user would see in the browser. Learn more at https://reactjs.org/docs/test-utils.html#act
        in ForwardRef(NavigationContainer)
Run Code Online (Sandbox Code Playgroud)

有很多我同步运行的测试并且成功了。但是在某些组件中,我确实运行了一些异步逻辑以获得所需的结果。

据我了解,我应该在act调用中包装任何异步代码。但是,即使在这种情况下,我也无法摆脱这个错误。


我继续尝试缩小问题的范围。现在,我所做的就是像这样渲染包装的组件:

test('a simple test', async () => {
  const component = (
    <NavigationContainer>
      <AppNavigator />
    </NavigationContainer>
  );

  const {queryByText} = render(component);
  expect(queryByText('test')).toBeNull();
});
Run Code Online (Sandbox Code Playgroud)

我仍然遇到同样的问题。请注意,实际测试成功,只是我仍然收到此控制台错误。

接下来,我尝试将render调用包装在actand 中waitForElement,因为这是我在运行异步逻辑时应该做的。不过好像这里的异步代码是渲染发生后才执行的。

所以我继续调查哪个部分NavigationContainer负责触发导致错误的异步逻辑,似乎这段代码(第 49-51 行)做了一些有趣的事情:

const [isReady, initialState = rest.initialState] = useThenable(
  getInitialState
);
Run Code Online (Sandbox Code Playgroud)

getInitialState是对useLinking(43-47) 前几行调用的返回值进行解构的结果。没有进一步详细说明,它getInitialState被包裹在那里的承诺中,所以它变成了“thenable”。

现在,如果我取消注释useThenable,控制台错误就会消失。但显然这不是我可以从这个文件之外轻松实现的。所以我有点卡在这里,因为我不知道如何以异步方式编写我的测试代码而不会一直遇到这个错误,而且我觉得忽略或抑制它也不是一个好主意。

任何帮助,将不胜感激。

Fer*_*gre 12

打完电话后我的建议render,从react-native-testing-library该做异步工作部件,useEffect(作为componentDidMount),改变状态,等等:

await act(async () => {})
Run Code Online (Sandbox Code Playgroud)

甚至:

await act(async () => await flushMicrotasksQueue())
Run Code Online (Sandbox Code Playgroud)

如果你有一些超时。