【问题标题】:How to test a React Native component that imports a custom native module with Jest?如何使用 Jest 测试导入自定义原生模块的 React Native 组件?
【发布时间】:2017-05-11 10:26:27
【问题描述】:

这是我尝试使用 React Native 0.39 和 Jest 18 测试的一个简单组件:

// index.ios.js

import React, { Component } from 'react';
import { AppRegistry, NativeModules, View } from 'react-native';

export default class TestProject extends Component {
  componentDidMount() {
    NativeModules.TestModule.test();
  }

  render() {
    return <View style={{ flex: 1 }} />;
  }
}

AppRegistry.registerComponent('TestProject', () => TestProject);

这是 TestModule 及其test 方法:

// ios/TestProject/TestModule.m

#import "TestModule.h"

@implementation TestModule

RCT_EXPORT_MODULE();

RCT_EXPORT_METHOD(test){
  NSLog(@"This is a test");
}

@end

以下测试失败,错误为TypeError: Cannot read property 'test' of undefined

// __tests__/index.ios.js

import 'react-native';
import renderer from 'react-test-renderer';
import React from 'react';
import Index from '../index.ios.js';

it('renders correctly', () => {
  const tree = renderer.create(
    <Index />
  );
});

我已阅读有关如何Mock native modules using jest.mock 的 Jest 文档,但仍不清楚如何扩展 Jest 的 NativeModules 模拟以包含我上面的 TestModule 类。

【问题讨论】:

    标签: ios facebook unit-testing react-native jestjs


    【解决方案1】:

    这对我来说也失败了(react-native 0.57.5,jest 23.6.0)。我能够找到一个解决方案,但它与这里完全不同(在我的情况下,这是一个更优雅的解决方案)。

    查看the ticket I filed了解更多详情。

    本质上,我必须通过作为第二个参数传递给 jest.mock() 的函数来充实 NativeModules,并将其放在使用 Jest 的 setupFiles 配置选项在每次测试开始时运行的脚本中。

    【讨论】:

      【解决方案2】:

      这样,您将模拟一次(在开玩笑开始之前)

      jest.config.js

      module.exports = {
        preset: 'react-native',
        setupFiles: ['./__mocks__/your-native-bridge.js']
      };
      

      __mocks__/your-native-bridge.js

      import {NativeModules} from 'react-native';
      
      NativeModules.YourNativeBridge = {
        property: jest.fn()
      };
      

      别忘了模拟YourNativeBridge中所有可能的函数、属性

      【讨论】:

      • 有人写过这些属性的完整列表吗?我不确定我需要哪些,所以我想他们都会做
      【解决方案3】:
      #__mocks__/react-native-modules
      
      const ReactNative = require('react-native')
      
      ReactNative.NativeModules = {
        Defaults: {
          RU: {
            publicKey: '',
            privateKey: '',
          },
        },
      }
      
      module.exports = ReactNative
      

      然后

      # in test file
      jest.mock('react-native-modules')
      import 'react-native-modules'
      

      【讨论】:

      • 这失败了:“无法设置属性 NativeModules of # 它只有一个 getter”
      【解决方案4】:

      你可以简单地在你的原生模块应该是的地方添加一个模拟:

      import {
        NativeModules,
      } from 'react-native';
      import React from 'react';
      import renderer from 'react-test-renderer';
      
      describe('TestProject', () => {
        beforeEach(() => {
          NativeModules.TestModule = { test: jest.fn() } 
        });
        ...
      });
      

      【讨论】:

      • 谢谢!传递给beforeEach 的函数缺少一个右花括号,但在其他方面就像一个魅力。我还选择使用beforeAll,因为这个设置只需要运行一次,而不是在每个规范之前运行。
      • 太好了,我添加了缺少的花括号。
      • 现在失败(0.57),因为您无法将属性添加到只读对象
      【解决方案5】:

      Jest 是一个 JavaScript 测试工具,它不会在原生模块中运行你用 Objective C/Swift/Java 编写的代码。您可以模拟本机模块的功能,以便您可以通过链接到的方法从 JavaScript 调用它。例如。

      jest.mock('NetInfo', () => {
        return {
          isConnected: {
            fetch: () => {
              return new Promise((accept, resolve) => {
                accept(true);
              })
            }
          }
        }
      });
      

      【讨论】:

      • 我认为这误解了我也有的问题。 OP 询问您如何模拟从react-native 导入的NativeModules.TestModule。我被困住了,因为react-native 需要导入,而不是模拟,react-test-renderer 覆盖才能工作。
      • @rgoldfinger 是正确的。我不是在尝试测试本机模块本身,而是尝试模拟 NativeModules.TestModule 以测试 index.ios.js
      • 有没有办法测试原生模块?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-24
      • 2017-09-05
      • 2018-07-13
      • 2017-03-24
      • 2019-10-30
      • 1970-01-01
      相关资源
      最近更新 更多