【问题标题】:Unable to mock native module无法模拟本机模块
【发布时间】:2016-12-16 14:10:37
【问题描述】:

我正在尝试测试我创建的一个组件,它使用来自react-native-mapsMapView 作为子组件。我知道我需要模拟那个原生组件,但我写的内容仍然会报错:

import 'react-native';
import React from 'react';
import Detail from '../js/components/Detail';

// Note: test renderer must be required after react-native.
import renderer from 'react-test-renderer';

jest.mock('react-native-maps', () => 'MapView');

it('renders correctly', () => {
  const tree = renderer.create(
    <Detail />
  ).toJSON();
  expect(tree).toMatchSnapshot();
});

以及我收到的错误:

TypeError: Cannot read property 'setNativeProps' of null

任何帮助将不胜感激。

编辑:如果有帮助,这是我要测试的组件...

import React, { Component } from 'react';
import {
  Dimensions,
  LayoutAnimation,
  StyleSheet,
  Text,
  TouchableHighlight,
  View,
} from 'react-native';
import MapView from 'react-native-maps';

import MapExpandButton from './buttons/MapExpandButton';

const styles = StyleSheet.create({
  ...
});

export default class AppointmentDetail extends Component {
  constructor(props) {
    super(props);
    this.state = {
      expanded: false,
    }
  }

  componentWillUpdate() {
    LayoutAnimation.easeInEaseOut();
  }

  renderMap() {
    return (
      <MapView
        initialRegion={{
          latitude: 51.501211,
          longitude: -0.110530,
          latitudeDelta: 0.005,
          longitudeDelta: 0.005,
        }}
        scrollEnabled={this.state.expanded}
        pitchEnabled={this.state.expanded}
        zoomEnabled={this.state.expanded}
        rotateEnabled={this.state.expanded}
        loadingEnabled={true}
        showsPointsOfInterest={false}
        style={[styles.map, this.state.expanded ? styles.mapExpanded : undefined]}>
        <MapView.Marker
          coordinate={{
            latitude: 51.501211,
            longitude: -0.110530,
          }}
          title='My Pin'
          description='Somewhere'
        />
      </MapView>
    );
  }

  renderSummary() {
    return (
      <View style={styles.section}>
        <Text style={styles.headline}>
          Appointment Type
        </Text>
        <Text style={styles.subheading}>
          on Date at Timeslot
        </Text>
      </View>
    );
  }

  renderAddress() {
    if (!this.state.expanded) {
      return (
        <View style={styles.section}>
          <Text style={styles.body}>
            Address Line 1,
          </Text>
          <Text style={styles.body}>
            Address Line 2,
          </Text>
          <Text style={styles.body}>
            City POSTCODE,
          </Text>
        </View>
      );
    }
  }

  renderSections() {
    return (
      <View>
        { this.renderSummary() }
        { this.renderAddress() }
      </View>
    );
  }

  toggleExpand() {
    const newExpandedState = !this.state.expanded;
    this.setState({ expanded: newExpandedState });
    if (this.props.didChangeExpandedState) {
      this.props.didChangeExpandedState(newExpandedState);
    }
  }

  render() {
    return (
      <View style={styles.container}>
        { this.renderMap() }
        { this.renderSections() }
        <View style={{ position: 'absolute', right: 8, top: 8 }}>
          <MapExpandButton onPress={this.toggleExpand.bind(this)} />
        </View>
      </View>
    );
  }
}

【问题讨论】:

    标签: unit-testing react-native jestjs


    【解决方案1】:

    在 GitHub 上找到了这个问题的解决方案:https://github.com/facebook/jest/issues/1960

    我认为问题在于 MapView.Marker 子组件没有被模拟。这个答案也在模拟子组件。

    jest.mock('react-native-maps', () => {
      return class MockMapView extends React.Component {
        static Marker = props => React.createElement('Marker', props, props.children);
        static propTypes = { children: React.PropTypes.any };
    
        render() {
          return React.createElement('MapView', this.props, this.props.children);
        }
      }
    });
    

    【讨论】:

    • 除此之外,还需要如下:jest.mock(`react-native-maps`, () =&gt; { const React = require('React'); });see this git issue
    【解决方案2】:

    当我遇到这个问题时,我将模块添加到 package.json 中 jest 下的忽略列表中:

    "transformIgnorePatterns": [
      "node_modules/(?!react-native|react-native-maps)"
    ]
    

    【讨论】:

    • 非常感谢,我会试一试。我使用了正确的名称吗?不确定是包名还是组件名
    • 是的,很确定你做对了。不过,您可能需要向 transformignorepatters 添加更多内容,我只是继续运行它,我收到的关于本机包的每个错误都扔在那里。
    • 好的,我已经添加了这个,并确保我为模拟函数使用了正确的名称,但我收到了这个错误Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. Check the render method of 'AppointmentDetail'.
    • 我想我现在已经知道了,它已经成功通过了来自 GitHub 的答案,如果你想看看,我会添加它作为答案。我认为问题在于我使用的是 MapView.Marker 子组件并且它们没有被嘲笑。
    猜你喜欢
    • 2022-01-21
    • 2019-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-13
    • 2021-11-06
    相关资源
    最近更新 更多