【问题标题】:mount() fails because target container is not dom elementmount() 失败,因为目标容器不是 dom 元素
【发布时间】:2018-11-06 15:40:31
【问题描述】:

我收到错误消息Target container is not a DOM element。使用 webpack。

完全错误:

FAIL  src/App.test.js
 ● Test suite failed to run

Invariant Violation: Target container is not a DOM element.

  at invariant (node_modules/fbjs/lib/invariant.js:42:15)
  at legacyRenderSubtreeIntoContainer (node_modules/react-dom/cjs/react-dom.development.js:17238:34)
  at Object.render (node_modules/react-dom/cjs/react-dom.development.js:17317:12)
  at Object.<anonymous> (src/index.js:32:20)
  at Object.<anonymous> (src/App.test.js:5:14)
      at <anonymous>
  at process._tickCallback (internal/process/next_tick.js:169:7)

App.js

import React, { Component } from 'react';
import './App.scss';
import Tables from './containers/Tables/Tables'

class App extends Component {
  render() {
    return (
        <Tables />
    );
  }
}

导出默认应用;

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { combineReducers, createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import aaaApi from '@aaa/aaajs';
import './index.css';
import App from './App';
import tableBuilderReducer from './store/reducers/tableBuilder'
import registerServiceWorker from './registerServiceWorker';    

const aaa = new aaaApi('xxx');

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

const reducers = {
  platforms: tableBuilderReducer('platforms'),
  regions: tableBuilderReducer('regions'),
  playback: tableBuilderReducer('playback')}

export const store = createStore(
  combineReducers(reducers),
  composeEnhancers(
    applyMiddleware(thunk.withExtraArgument(aaa)),
  ),
);

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
)

registerServiceWorker();

App.test.js

import React from 'react'
import Enzyme, { mount, shallow } from 'enzyme'
import Adapter from 'enzyme-adapter-react-16'
import App from './App' 
import { store } from './index.js'

Enzyme.configure({ adapter: new Adapter() })

function setup() {
    const props = {
        sortColumnHandler: jest.fn()
    }

    const enzymeWraper = mount(<App />)

    return {
        props,
        enzymeWraper
    }
}

describe('components', ()=> {
    describe('Tables', () => {
        it('should render self and sub-components', () => {
            const { enzymeWraper }  = setup()
        })
    })
})

【问题讨论】:

  • 你能展示一下 App.js 的代码吗?
  • @brian-lives-outdoors 添加了!
  • 问题是,当 Jest 运行 App.test.js 时,不知何故 index.js 被包含在内。我从App.test.jsApp.js 看不到任何明显的东西。 index.js 是否包含在 Jest 配置文件中(setupFiles 等?)
  • @brian-lives-outdoors 这是我第一次编写测试代码,其他人设置了它,所以我不确定我应该看哪里,但我唯一能找到的是@987654331 @ in config/paths.js 我认为这应该不是问题...?
  • @brian-lives-outdoors 我想我找到了。我在App.test.js 中有import { store } from './index.js',当我清理要在此处发布的代码时,我没有将其包含在帖子中。但是删除它会给我另一个错误,即Invariant Violation: Could not find "store" in either the context or props of "Connect(Component)". Either wrap the root component in a &lt;Provider&gt;, or explicitly pass "store" as a prop to "Connect(Component)"

标签: reactjs unit-testing jestjs enzyme


【解决方案1】:

问题是由 index.js 包含在测试中引起的,并且当在 Jest 中的 jsdom 环境创建的文档中找不到 root 时在 ReactDOM.render() 处失败。

App.test.js 中不需要import { store } from './index.js',因此删除它可以修复初始错误。

使用enzyme 中的mount 执行full DOM rendering 并要求所有内容都设置为完整渲染。它只能用于对使用生命周期方法、与 DOM 交互等的组件进行单元测试。它将完全呈现正在测试的组件和所有子组件。在这种情况下,App 的子代使用 redux 存储,因此需要在包装 Provider 中提供存储,以便使用 mount 进行完整渲染。

在大多数情况下,应使用 shallow 对 React 组件进行单元测试。它执行shallow rendering of just the component being tested。在这种情况下,App 是一个简单的无状态组件,其中包含 Tables,因此使用 shallow 是正确的方法。

额外提示:

enzyme-to-json 安装为开发依赖项,将其作为快照序列化程序添加到Jest,App.test.js 被简化为:

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

describe("App", () => {

  it('renders as expected', () => {
    const component = shallow(<App />);
    expect(component).toMatchSnapshot();
  });

});

【讨论】:

  • 太好了,成功了!还有一件事,App 组件确实有一个子组件Tables,它使用connect 获取道具并在componentDidMount 中进行ajax 调用。在这种情况下,我是否应该使用 mount 单独测试 Tables 组件?
  • 是的,单独测试一下。是的,如果一个组件在componentDidMount 中有逻辑,那么使用mount 是测试它的唯一方法。听起来您必须将Tables 包装在Providermount 中。 (...并且您需要模拟 ajax 调用,以便您的单元测试不会引起网络请求)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-24
  • 1970-01-01
  • 2022-08-17
  • 2014-07-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多