首页 > 解决方案 > 在构造函数中使用 Enzyme 进行 React Native 的 Jest 抛出丢失的 super() 调用

问题描述

在完成所有设置和工作时遇到一些麻烦,这是我的环境

Environment:
  OS: macOS 10.14.2
  Node: 8.9.0
  Yarn: 1.5.1
  npm: 6.4.1
  Watchman: 4.9.0
  Xcode: Xcode 10.1 Build version 10B61
  Android Studio: 3.2 AI-181.5540.7.32.5056338

Packages: (wanted => installed)
  react: 16.3.1 => 16.3.1
  react-native: 0.55.4 => 0.55.4

这是jest我的配置package.json

"jest": {
    "preset": "react-native",
    "transformIgnorePatterns": [
      "node_modules/(?!react-native|react-navigation)/"
    ],
    "coverageThreshold": {
      "global": {
        "statements": 80
      }
    },
    "moduleFileExtensions": [
      "js",
      "jsx"
    ],
    "moduleDirectories": [
      "node_modules"
    ],
    "snapshotSerializers": ["enzyme-to-json/serializer"],
    "setupTestFrameworkScriptFile": "./setup-tests.js",
    "setupFiles": ["./setup.js"]
  }

setup-tests.js文件中我有这个设置

import 'react-native';
import 'jest-enzyme';
import Adapter from 'enzyme-adapter-react-16';
import Enzyme from 'enzyme';

/**
 * Set up DOM in node.js environment for Enzyme to mount to
 */
const { JSDOM } = require('jsdom');

const jsdom = new JSDOM('<!doctype html><html><body></body></html>');
const { window } = jsdom;

function copyProps(src, target) {
  Object.defineProperties(target, {
    ...Object.getOwnPropertyDescriptors(src),
    ...Object.getOwnPropertyDescriptors(target),
  });
}

global.window = window;
global.document = window.document;
global.navigator = {
  userAgent: 'node.js',
};
copyProps(window, global);

/**
 * Set up Enzyme to mount to DOM, simulate events,
 * and inspect the DOM in tests.
 */
Enzyme.configure({ adapter: new Adapter() });

/**
 * Ignore some expected warnings
 * see: https://jestjs.io/docs/en/tutorial-react.html#snapshot-testing-with-mocks-enzyme-and-react-16
 * see https://github.com/Root-App/react-native-mock-render/issues/6
 */
const originalConsoleError = console.error;
console.error = (message) => {
  if (message.startsWith('Warning:')) {
    return;
  }

  originalConsoleError(message);
};

setup.js

import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
configure({ adapter: new Adapter() });

我从酶网站上的这个页面得到的

https://airbnb.io/enzyme/docs/guides/react-native.html

依赖版本是

"babel-core": "^6.26.3",
"babel-jest": "23.6.0",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react-native": "4.0.1",
"enzyme": "^3.8.0",
"enzyme-adapter-react-16": "^1.7.1",
"enzyme-to-json": "^3.3.5",
"jest": "23.6.0",
"jest-enzyme": "^7.0.1",
"jest-serializer-enzyme": "^1.0.0",
"jsdom": "^13.2.0",
"react-addons-test-utils": "^15.6.2",
"react-dom": "^16.7.0",
"react-native-mock-render": "^0.1.2",
"react-test-renderer": "16.3.1"

我得到的具体错误是

***/node_modules/jsdom/lib/jsdom/living/generated/Element.js: missing super() call in constructor

        15 | 
        16 | class Element extends Node.interface {
      > 17 |   constructor() {
           |   ^
        18 |     throw new TypeError("Illegal constructor");
        19 |   }
        20 | 

我为此尝试了许多不同的配置,但似乎无法克服这个错误。

这是测试文件

import 'react-native';
import React from 'react';
import {Login} from './index';
import { mount } from 'enzyme';


it('renders correctly', () => {
  const wrapper = mount(
    <Login />
  );
  expect(wrapper).toMatchSnapshot();
});

我已经配对了我实际测试的文件,以尝试删除任何可能的外部库问题

import React from 'react';
import {
  View,
  Text
} from 'react-native';

export class Login extends React.Component {
  render() {
    return (
      <View>
        <Text>Hello World</Text>
      </View>
    );
  }
}

export default Login;

这里的命名导出和默认导出没有区别,但通常默认导出连接到 redux,所以我导出命名类进行测试。

标签: javascriptreact-nativejestjsenzymejsdom

解决方案


您显示的依赖项表明您正在使用 Babel 6。Babel 6 中有一个错误会导致您在问题中描述的那种问题。这里这里都有报道。

你应该升级到 Babel 7。


简而言之,问题是在 Babel 修复之前,Babel 正在super()对代码进行静态分析,在静态分析期间发现没有被调用并导致代码失败。但是,规则是super()必须在访问构造函数thisthis从构造函数返回之前调用。(如果构造函数没有显式返回值,则返回this。)由于您显示失败的构造函数抛出,它不会返回,因此它不必调用super().


推荐阅读