反应导航:如何测试使用withNavigation HOC的组件?

时间:2019-08-16 13:27:37

标签: react-native jestjs react-navigation higher-order-components react-testing-library

我正在用Jest为我的React Native应用程序编写单元测试。我有一个包裹在withNavigation HOC.

中的组件

我的问题是我的测试崩溃了,并抛出:

● LoginScreen component › given no props: should render a login form

    Invariant Violation: withNavigation can only be used on a view hierarchy of a navigator. The wrapped component is unable to get access to navigation from props or context.

我正在使用@testing-library/react-native进行测试,而我set up a custom render method是这样的:

import { render } from '@testing-library/react-native';
import React from 'react';
import { NavigationContext } from 'react-navigation';
import { Provider } from 'react-redux';

import store from '../src/store';

const WithProviders = ({ children }) => {
  return (
    <Provider store={store}>
      <NavigationContext.Provider>{children}</NavigationContext.Provider>
    </Provider>
  );
};

const customRender = (ui, options) =>
  render(ui, {
    wrapper: WithProviders,
    ...options,
  });

export * from '@testing-library/react-native';

export { customRender as render };

这适用于Redux上下文,但不适用于导航提供程序。

您如何测试withNavigation HOC中包装的组件?

更新

我尝试了这样的建议答案:

jest.mock('react-navigation', () => ({
  withNavigation: Component => props => <Component {...props} />,
}));

afterAll(() => {
  jest.restoreAllMocks();
});

但这不起作用。我收到错误消息:

Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

2 个答案:

答案 0 :(得分:3)

根据Kubilay的回答,这是我的解决方法:

jest.mock('react-navigation', () => ({
  withNavigation: Component => props => (
    <Component navigation={{ navigate: jest.fn() }} {...props} />
  ),
  SafeAreaView: ({ children }) => <>{children}</>,
}));

afterAll(() => {
  jest.restoreAllMocks();
});

我不得不嘲笑withNavigationSafeAreaView

这仍然是非常不令人满意的方式。如果有人知道如何在自定义渲染方法中注入正确的React Navigation提供程序,我将非常感谢。

理想情况下,应该有一种配置将内容包装在容器中的自定义渲染器的方法。这是我使用Redux的方法。

import { render } from '@testing-library/react-native';
import React from 'react';
import { Provider } from 'react-redux';

import configureStore from '../src/redux/store.js';

const store = configureStore();

const WithProviders = ({ children }) => (
  <Provider store={store}>{children}</Provider>
);

const customRender = (ui, options) =>
  render(ui, { wrapper: WithProviders, ...options });

export * from '@testing-library/react-native';

export { customRender as render };

答案 1 :(得分:1)

您应该像这样模拟反应导航:

jest.mock("react-navigation", ({ withNavigation: (component) => component })

然后将道具传递到您的组件:

const mockProps = {
    navigation: { navigate: jest.fn() }
}

wrapper = shallow(<LoginScreen {...mockProps}/>)