Javascript 测试 React:目标容器不是 DOM 元素

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/39986178/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 23:07:27  来源:igfitidea点击:

Testing React: Target Container is not a DOM element

javascriptreactjsecmascript-6tdd

提问by ilrein

I'm attempting to test a React component with Jest/Enzyme while using Webpack.

我正在尝试在使用 Webpack 时使用 Jest/Enzyme 测试 React 组件。

I have a very simple test @

我有一个非常简单的测试@

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

import App from './App';

it('App', () => {
  const app = shallow(<App />);
  expect(1).toEqual(1);
});

The relative component it's picking up is :

它拾取的相关组件是:

import React, { Component } from 'react';
import { render } from 'react-dom';

// import './styles/normalize.css';

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

render(<App />, document.getElementById('app'));

However, running jestcauses a failure:

但是,运行jest会导致失败:

Invariant Violation: _registerComponent(...): Target container is not a DOM element.

Invariant Violation: _registerComponent(...): Target container is not a DOM element.

With errors @

有错误@

at Object.<anonymous> (src/App.js:14:48) at Object.<anonymous> (src/App.test.js:4:38)

at Object.<anonymous> (src/App.js:14:48) at Object.<anonymous> (src/App.test.js:4:38)

The test files references line 4, which is the import of <App />, that causes a fail. The stack trace says line 14 of App.jsis the reason for the failure -- which is nothing more than the render call from react-dom, something I've never had a challenge with (the app renders properly from my Webpack setup).

测试文件引用第 4 行,它是 的导入<App />,导致失败。堆栈跟踪说第 14 行App.js是失败的原因——这只不过是来自 的渲染调用react-dom,这是我从未遇到过的挑战(应用程序从我的 Webpack 设置中正确渲染)。

For those interested (Webpack code):

对于那些感兴趣的人(Webpack 代码):

module.exports = {
  entry: './src/App',
  output: {
    filename: 'bundle.js',
    path: './dist'
  },
  module: {
    loaders: [
      {
        test: /\.js?$/,
        exclude: /node_modules/,
        loader: 'babel',
        query: {
          presets: ['react', 'es2015']
        }
      },
      {
        test: /\.css$/,
        loader: 'style!css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]'
      },
      {
        test: /\.scss$/,
        loader: 'style!css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!sass'
      }
    ]
  }
}

And my package.json:

而我的package.json

{
  "name": "tic-tac-dux",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "webpack-dev-server --devtool eval --progress --colors --inline --hot --content-base dist/",
    "test": "jest"
  },
  "jest": {
    "moduleNameMapper": {
      "^.+\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
      "^.+\.(css|sass)$": "<rootDir>/__mocks__/styleMock.js"
    }
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "babel-core": "^6.17.0",
    "babel-jest": "^16.0.0",
    "babel-loader": "^6.2.5",
    "babel-polyfill": "^6.16.0",
    "babel-preset-es2015": "^6.16.0",
    "babel-preset-react": "^6.16.0",
    "css-loader": "^0.25.0",
    "enzyme": "^2.4.1",
    "jest": "^16.0.1",
    "jest-cli": "^16.0.1",
    "node-sass": "^3.10.1",
    "react-addons-test-utils": "^15.3.2",
    "react-dom": "^15.3.2",
    "sass-loader": "^4.0.2",
    "style-loader": "^0.13.1",
    "webpack": "^1.13.2",
    "webpack-dev-server": "^1.16.2"
  },
  "dependencies": {
    "react": "^15.3.2",
    "react-dom": "^15.3.2"
  }
}

Oh, and if anyone is going to say that the div element isn't being loaded before the script, here's my index.html:

哦,如果有人要说在脚本之前没有加载 div 元素,这是我的index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>App</title>
  </head>
  <body>
    <div id="app"></div>
    <script src="/bundle.js"></script>
  </body>
</html>

What could be the reason for this peculiar rendering problem? Something to do with a new Jest update to 15.0?

这个特殊的渲染问题可能是什么原因?与 15.0 的新 Jest 更新有关吗?

回答by Zachary Bennett

For anyone else that was combing through the internet like I've been - looking for a solution to this when testing with Jest - I will back up the answer by @biphobe by saying Jest will cause this error to occur when you export something inside the same file that is calling ReactDOM.render.

对于像我一样通过互联网梳理的其他任何人 - 在使用 Jest 进行测试时寻找解决方案 - 我将通过@biphobe 支持答案,说 Jest 会在您导出某些内容时导致此错误发生调用 ReactDOM.render 的同一个文件。

In my case, I was exporting an object within my index.js where I was also calling ReactDOM.render. I removed this export and voila!

就我而言,我在 index.js 中导出了一个对象,我也在其中调用了 ReactDOM.render。我删除了这个导出,瞧!

回答by biphobe

App.jsxis supposed to export the App class and do nothing more, rendershould be called elsewhere.

App.jsx应该导出 App 类,什么也不做,render应该在别处调用。

If you remove the rendercall from the App.jsx error should disappear, it pops up because the test environment doesn't supply the DOM with an appid.

如果render从 App.jsx 中删除调用错误应该消失,它会弹出,因为测试环境没有为 DOM 提供appid。

回答by Islam Murtazaev

As I see, this error arises in many cases and requires different approaches to solve it. My scenario is not the same as the example above, I use redux & router, although I was struggling with the same error. What helped me to solve this problem is to change index.jsfrom:

正如我所见,这个错误在很多情况下都会出现,需要不同的方法来解决。我的场景与上面的示例不同,我使用redux & router,尽管我遇到了同样的错误。帮助我解决这个问题的是index.js从:

ReactDOM.render(
  <Provider store={store}>
    <AppRouter />
  </Provider>,
  document.getElementById("root")
);
registerServiceWorker();

to:

到:

ReactDOM.render(
    (<Provider store={store}>
        <AppRouter/>
    </Provider>),
     document.getElementById('root') || document.createElement('div') // for testing purposes
);
registerServiceWorker();

回答by Nono

I found a solution for this error to my use case: Using the same Redux store React is using outside of React.

我为我的用例找到了针对此错误的解决方案:使用 React 在 React 之外使用的相同 Redux 存储。

In trying to export my React's Redux storefrom index.tsxto be used somewhere else outside of the React application, I was getting the same error while running Jest tests (which make use of Enzyme) in the App.tsxfile.

在尝试汇出我的阵营的终极版storeindex.tsx使用别的地方以外的应用做出反应,我得到了同样的错误,同时运行玩笑测试(其中利用酶)中App.tsx的文件。

The error

错误

The initial code that didn't work when testing React looked like this.

测试 React 时不起作用的初始代码如下所示。

// index.tsx

import * as React from "react";
import { render } from "react-dom";
import { Provider } from "react-redux";
import { applyMiddleware, compose, createStore } from "redux";
import App from "./components/App";
import { rootReducer } from "./store/reducers";
import { initialState } from "./store/state";

const middlewares = [];

export const store = createStore(
    rootReducer,
    initialState,
    compose(applyMiddleware(...middlewares)),
);

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

The solution that worked for me

对我有用的解决方案

Separate the Redux store logic into a new file named store.ts, then create a default export(to be used by index.tsx, i.e., the React application) and a non-default export with export const store(to be used from non-React classes), as follows.

将 Redux 存储逻辑分离到一个名为 的新文件中store.ts,然后创建一个default export(供index.tsx,即 React 应用程序使用)和一个非默认导出 with export const store(供非 React 类使用),如下所示。

// store.ts

import { applyMiddleware, compose, createStore } from "redux";
import logger from "redux-logger";
import { rootReducer } from "./store/reducers";
import { initialState } from "./store/state";

const middlewares = [];

export const store = createStore(
    rootReducer,
    initialState,
    compose(applyMiddleware(...middlewares)),
);

export default store;
// updated index.tsx

import * as React from "react";
import { render } from "react-dom";
import { Provider } from "react-redux";
import App from "./components/App";
import store from "./store";

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

Using the Redux store in non-React classes

在非 React 类中使用 Redux 存储

// MyClass.ts

import { store } from "./store"; // store.ts

export default class MyClass {
  handleClick() {
    store.dispatch({ ...new SomeAction() });
  }
}

The defaultexport

default出口

A small note before you go. Here is how to use the defaultand the non-default exports.

走之前的小纸条。以下是如何使用default和非默认导出。

  • default export store;is used with import store from "./store";
  • export const store = ...is used with import { store } from "./store";
  • default export store;import store from "./store";
  • export const store = ...import { store } from "./store";

Hope this helps!

希望这可以帮助!

https://nono.ma/says/solved-invariant-violation-target-container-is-not-a-dom-element

https://nono.ma/says/solved-invariant-violation-target-container-is-not-a-dom-element