Unit testing React-Native中的非组件单元测试

Unit testing React-Native中的非组件单元测试,unit-testing,react-native,Unit Testing,React Native,我想为React Native/TypeScript应用程序编写一些单元测试。问题是有些库不在开发环境下运行,比如“AsyncStorage”或“react-native-sqlite-2” 我在Jest网站上发现的唯一一件事是关于模拟,但这只是一种分离UI测试的方法 我正在考虑使用一些node.js库来模拟这些库,根据环境加载正确的库 比如: if(isDevelopment) { SQLiteDatabase = require("./sqlite_database_node").S

我想为React Native/TypeScript应用程序编写一些单元测试。问题是有些库不在开发环境下运行,比如“AsyncStorage”或“react-native-sqlite-2”

我在Jest网站上发现的唯一一件事是关于模拟,但这只是一种分离UI测试的方法

我正在考虑使用一些node.js库来模拟这些库,根据环境加载正确的库

比如:

if(isDevelopment) {
    SQLiteDatabase = require("./sqlite_database_node").SQLiteDatabaseNode;
}
else {
    SQLiteDatabase = require("./sqlite_database_rn").SQLiteDatabaseRN;
}

这是解决这个问题的正确方法吗?如果是,我如何导入/要求它工作?如果没有,最好的方法是什么?

当您运行Jest或任何单元测试时。测试正在节点环境上运行。 因此,当您尝试访问具有本机组件/库(例如:异步存储或SQLite)的模块时,代码将在测试环境中中断

为了解决这个问题,Jest提出了模块模拟。 所以我在我的项目中所做的是,对于我使用的任何在内部使用本机模块的node_模块。。我为它创建了一个全局模拟

要做到这一点,您只需在根目录上创建一个文件夹
\uuuuu mocks\uuuu
,如下所示

.
├── README.md
├── __mocks__
│   ├── base-64.js
│   ├── react-native-animatable.js
│   ├── react-native-config.js
│   ├── react-native-device-info.js
│   ├── react-native-fetch-blob.js
│   ├── react-native-firebase.js
│   ├── react-native-google-analytics-bridge.js
│   ├── react-native-map-markerclustering.js
│   ├── react-native-maps.js
│   ├── react-native-simple-download-manager.js
│   ├── react-native-simple-toast.js
│   ├── react-native-splash-screen.js
│   ├── react-native-testfairy.js
│   ├── react-native-version-number.js
│   └── react-native.js
├── __tests__
│   └── index.test.js
├── app
│   ├── App.container.js
│   ├── __tests__
│   ├── assets
│   ├── components
│   ├── config
│   ├── index.js
│   ├── language
│   ├── pages
│   ├── redux
│   ├── routes
│   ├── themes
│   └── utils
├── app.json
├── circle.yml
├── index.js
├── package.json
└── yarn.lock
作为一个例子,让我们看看

\uuuu mocks\uuuu/react native firebase.js

module.exports = {
  crash: () => ({
    setCrashCollectionEnabled: jest.fn()
  }),
  auth: () => ({
    signInAnonymously: jest.fn()
  }),
  database: () => ({
    ref: () => ({
      on: jest.fn()
    })
  }),
  config: () => ({
    fetch: jest.fn(),
    setDefaults: jest.fn(),
    getValue: jest.fn()
  }),
  messaging: jest.fn(() => ({
    requestPermissions: jest.fn(),
    subscribeToTopic: jest.fn(),
    getToken: jest.fn(Promise.resolve),
    onMessage: jest.fn(),
    getInitialNotification: jest.fn(Promise.resolve),
    onTokenRefresh: jest.fn()
  }))
};
或者您可能
\uuuu mocks\uuuu/react native device info


const mockmod=jest.genMockFromModule('react-native-device-info');
module.exports=mockmod;

重点是。。在测试期间,当您执行
require('react-native-device-info')


因此,在test env u中将运行一个模拟模块,而在app env中,您将拥有实际的节点模块。

当您运行Jest或任何单元测试时。测试正在节点环境上运行。 因此,当您尝试访问具有本机组件/库(例如:异步存储或SQLite)的模块时,代码将在测试环境中中断

为了解决这个问题,Jest提出了模块模拟。 所以我在我的项目中所做的是,对于我使用的任何在内部使用本机模块的node_模块。。我为它创建了一个全局模拟

要做到这一点,您只需在根目录上创建一个文件夹
\uuuuu mocks\uuuu
,如下所示

.
├── README.md
├── __mocks__
│   ├── base-64.js
│   ├── react-native-animatable.js
│   ├── react-native-config.js
│   ├── react-native-device-info.js
│   ├── react-native-fetch-blob.js
│   ├── react-native-firebase.js
│   ├── react-native-google-analytics-bridge.js
│   ├── react-native-map-markerclustering.js
│   ├── react-native-maps.js
│   ├── react-native-simple-download-manager.js
│   ├── react-native-simple-toast.js
│   ├── react-native-splash-screen.js
│   ├── react-native-testfairy.js
│   ├── react-native-version-number.js
│   └── react-native.js
├── __tests__
│   └── index.test.js
├── app
│   ├── App.container.js
│   ├── __tests__
│   ├── assets
│   ├── components
│   ├── config
│   ├── index.js
│   ├── language
│   ├── pages
│   ├── redux
│   ├── routes
│   ├── themes
│   └── utils
├── app.json
├── circle.yml
├── index.js
├── package.json
└── yarn.lock
作为一个例子,让我们看看

\uuuu mocks\uuuu/react native firebase.js

module.exports = {
  crash: () => ({
    setCrashCollectionEnabled: jest.fn()
  }),
  auth: () => ({
    signInAnonymously: jest.fn()
  }),
  database: () => ({
    ref: () => ({
      on: jest.fn()
    })
  }),
  config: () => ({
    fetch: jest.fn(),
    setDefaults: jest.fn(),
    getValue: jest.fn()
  }),
  messaging: jest.fn(() => ({
    requestPermissions: jest.fn(),
    subscribeToTopic: jest.fn(),
    getToken: jest.fn(Promise.resolve),
    onMessage: jest.fn(),
    getInitialNotification: jest.fn(Promise.resolve),
    onTokenRefresh: jest.fn()
  }))
};
或者您可能
\uuuu mocks\uuuu/react native device info


const mockmod=jest.genMockFromModule('react-native-device-info');
module.exports=mockmod;

重点是。。在测试期间,当您执行
require('react-native-device-info')


因此,在test env u中将运行一个模拟模块,而在app env中,您将拥有实际的节点模块。

如果您有纯单元测试,而这些测试不涉及React本机组件中的代码,那么您为什么需要模拟任何东西。如果有人在独立于react-native(如域层)的JS模块上编写单元测试,而react-native位于react-native项目的下面,那么应该能够在没有任何本机依赖的情况下对裸露的JS逻辑进行单元测试。你会怎么安排?现在,如果我尝试运行单元测试,这些测试只是功能测试,而不是在react组件上,我仍然会得到“不变冲突:本机模块不能为null”,我同意,我已经花了两周的时间评估react native,尽管它在组件级别带来了诸多好处,但实际上构建一个正确分层的大型应用程序,并且单独测试这些分层是一件非常痛苦的事情。在这一点上,我的印象是,即使是大型的react原生项目也只是在进行e2e测试后才进行模拟和测试,对于大型团队来说,这可能没问题,但是当试图与5-6人一起工作时,几乎没有保证较低的层在react本机环境中工作会很糟糕。如果您有纯单元测试,而这些测试不涉及react本机组件中的代码,那么您为什么需要模拟任何东西呢。如果有人在独立于react-native(如域层)的JS模块上编写单元测试,而react-native位于react-native项目的下面,那么应该能够在没有任何本机依赖的情况下对裸露的JS逻辑进行单元测试。你会怎么安排?现在,如果我尝试运行单元测试,这些测试只是功能测试,而不是在react组件上,我仍然会得到“不变冲突:本机模块不能为null”,我同意,我已经花了两周的时间评估react native,尽管它在组件级别带来了诸多好处,但实际上构建一个正确分层的大型应用程序,并且单独测试这些分层是一件非常痛苦的事情。在这一点上,我的印象是,即使是大型react本机项目,也只是在进行e2e测试后才进行模拟和测试,对于大型团队来说,这可能没什么问题,但当试图与5-6人一起工作时,几乎没有任何保证,在react本机环境下,较低的层将工作,这是一个严重的问题。