React & Jest 测试:连接到 Redux 的嵌套组件给出了 Invariant Violation 错误

IT技术 reactjs testing redux jestjs
2021-05-11 22:36:05

所以我导入了一个组件来使用 Jest 进行一些测试。

class MyComponent extends Component {
  render() {
    return (
      <div>
        <OtherComponent />
      </div>
    );
  }
}

export { MyComponent };

其中另一个组件定义为:

class OtherComponent extends Component { ... }
export default connect(...)(OtherComponent);

我的测试如下:

import React from 'react';
import { shallow } from 'enzyme';

import { MyComponent } from '../../components/MyComponent';
// ...

事实上,在 MyComponent 内部有其他组件,它使用 connect 连接到 Redux 使得上面的测试文件中的导入失败:

不变违规:_registerComponent(...):目标容器不是 DOM 元素。

  at invariant (node_modules/fbjs/lib/invariant.js:44:15)
  at Object._renderNewRootComponent (node_modules/react-dom/lib/ReactMount.js:311:76)
  at Object._renderSubtreeIntoContainer (node_modules/react-dom/lib/ReactMount.js:401:32)
  at Object.render (node_modules/react-dom/lib/ReactMount.js:422:23)
  at Object.<anonymous> (my-app-directory/index.js:30:46)
  at Object.<anonymous> (my-app-directory/components/OtherComponent.js:x:xx)
  at Object.<anonymous> (my-app-directory/components/MyComponent.js:x:xx)
  at Object.<anonymous> (my-app-directory/test/components/MyComponent.test.js:x:xx)
  at handle (node_modules/worker-farm/lib/child/index.js:41:8)
  at process.<anonymous> (node_modules/worker-farm/lib/child/index.js:47:3)
  at emitTwo (events.js:106:13)
  at process.emit (events.js:191:7)
  at process.nextTick (internal/child_process.js:744:12)
  at _combinedTickCallback (internal/process/next_tick.js:67:7)
  at process._tickCallback (internal/process/next_tick.js:98:9)

那么如果嵌套组件连接到 Redux,我该如何测试我的组件呢?O_O'

更新:

我从我的主应用程序文件index.js 中从 react-router 导入历史记录,并调用它在我的其他组件方法之一中推送新路由。这似乎是导致问题的原因。所以我想我不应该在我的组件中使用历史记录?如果我选择保持这种方式,我将如何在我的测试中处理它?

import { history } from '../'; // index.js file with ReactDOM injection

class OtherComponent extends Component { 
  // ...
  someMethod() {
    callSomeActionCreator();
    history.push('/some/route');
  }
}
2个回答

单元测试的一种方法是只关注实际组件并只测试其行为。为此,您必须模拟所有其他依赖项。在您的情况下,您可以模拟OtherComponent,然后测试它是否与正确的参数一起使用。

import React from 'react';
import { shallow } from 'enzyme';
import { MyComponent } from '../../components/MyComponent';

jest.mock('../../OtherComponent', () => 'OtherComponent')//note that the path is relative to your test files

这将替换OtherComponent为一个名为 name 的简单组件OtherComponent

澄清一下,不变违规错误并不是使用react-redux. 相反,当没有提供挂载到 DOM 的方法时,测试套件会失败(这与尝试调用.render不在 DOM 中的元素时ReactDOM 会失败的原因大致相同)。

回应@Andreas 所说的 - 您可以jest.mock在测试设置期间使用它来初始化 ReactDOM。然后,react-redux具体来说,您可以将 传递store给经过测试的组件作为props:

import Timer from './Timer';
import { store } from './store';

jest.mock("./index.js", () => "root");

describe('Timer test: ', () => {
  it('should render', () => {
    const wrapper = <Timer store={store} />
    expect(wrapper);
  });
});

关于您的更新:React Router 提供了一个很好的示例,说明如何在此处测试应用程序的导航相关方面您可以提供的其他参数也jest.mock可能会派上用场。