首页 文章

React&Jest测试:连接到Redux的嵌套组件会产生Invariant Violation错误

提问于
浏览
2

所以我有一个组件,我导入以使用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内部存在OtherComponent,使用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”

Update:

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

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

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

2 回答

  • 4

    单元测试的一种方法是仅关注实际组件并仅测试其行为 . 为此,您必须模拟所有其他依赖项 . 在你的情况下,你可以模拟出 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 的简单组件替换 OtherComponent .

  • 1

    只是为了澄清,使用 react-redux 进行测试时,不变违规错误并不是唯一的 . 相反,当测试套件没有提供安装到DOM上的方法时,测试套件会失败(因为如果你试图在不在DOM中的元素上调用 .render ,ReactDOM会失败的原因相同) .

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

    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提供了一个很好的示例,说明如何测试App的导航相关方面here.您可以为jest.mock提供的其他参数也可以派上用场 .

相关问题