Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

如何配置并编写react-native的jest单元测试? #9470

Closed
Saifa-96 opened this issue Jun 7, 2021 · 10 comments
Closed

如何配置并编写react-native的jest单元测试? #9470

Saifa-96 opened this issue Jun 7, 2021 · 10 comments
Labels
enhancement New feature or request T-rn Target - 编译到 React Native V-3 Version - 3.x

Comments

@Saifa-96
Copy link

Saifa-96 commented Jun 7, 2021

这个特性解决了什么问题?

想做react-native的单元测试,但是遇到报错如下:

    Test suite failed to run

    Jest encountered an unexpected token

    This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.

    By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".

    Here's what you can do:
     • If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/en/ecmascript-modules for how to enable it.
     • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
     • If you need a custom transformation specify a "transform" option in your config.
     • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

    You'll find more details and examples of these config options in the docs:
    https://jestjs.io/docs/en/configuration.html

    Details:

    /Users/xxx/Documents/project/project-name/node_modules/react-native/Libraries/vendor/core/ErrorUtils.js:11
    import type {ErrorUtilsT} from '@react-native/polyfills/error-guard';
    ^^^^^^

    SyntaxError: Cannot use import statement outside a module

      at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1350:14)
      at Object.<anonymous> (node_modules/react-native/jest/setup.js:37:3)

我的jest.config.js配置如下:

module.exports = {
  preset: "react-native",
  verbose: true,
  globals: {
    IS_RN: true
  },
  moduleNameMapper: {
    "@tarojs/taro": "@tarojs/taro-rn",
    "@tarojs/components": "@tarojs/components-rn/dist/react",
    // "^. \\.(css|scss|less)$": "<rootDir>/__mocks__/style-mock.js",
    "^. \\.(css|scss|less)$": "identity-obj-proxy",
    "^@/(.*)$": "<rootDir>/src/$1"
  },
  transform: {
    // 设置babel-jest转译es6 es7代码
    // "^. \\.(js|jsx|ts|tsx)$": "babel-jest",
    // 项目中采用typescript为技术栈,需要设置ts-jest转译代码
    // "^. \\.(ts|tsx)$": "ts-jest",
    // "^. \\.esm.js?$": "ts-jest"
    '^. \\.js$': '<rootDir>/node_modules/react-native/jest/preprocessor.js',
    '^. \\.tsx?$': 'ts-jest'
  },
  rootDir: __dirname,
  setupFiles: ["<rootDir>/jest-setup"],
  moduleFileExtensions: ["js", "jsx", "ts", "tsx", "json"],
  transformIgnorePatterns: [
    "<rootDir>/node_modules/(?!@taro|@react-native)",
    "^. \\.(css|sass|scss|less)$"
  ],
  testPathIgnorePatterns: ["/node_modules/"]
};

taro版本如下:

👽 Taro v3.2.9


  Taro CLI 3.2.9 environment info:
    System:
      OS: macOS 11.2.3
      Shell: 5.8 - /bin/zsh
    Binaries:
      Node: 14.7.0 - ~/.nvm/versions/node/v14.7.0/bin/node
      Yarn: 1.22.10 - ~/.nvm/versions/node/v14.7.0/bin/yarn
      npm: 6.14.7 - ~/.nvm/versions/node/v14.7.0/bin/npm
    npmPackages:
      @tarojs/cli: 3.2.9 => 3.2.9 
      @tarojs/components: 3.2.9 => 3.2.9 
      @tarojs/mini-runner: 3.2.9 => 3.2.9 
      @tarojs/react: 3.2.9 => 3.2.9 
      @tarojs/runtime: 3.2.9 => 3.2.9 
      @tarojs/taro: 3.2.9 => 3.2.9 
      @tarojs/webpack-runner: 3.2.9 => 3.2.9 
      babel-preset-taro: 3.2.9 => 3.2.9 
      eslint-config-taro: 3.2.9 => 3.2.9 
      react: 17.0.2 => 17.0.2 
      react-native: 0.64.0 => 0.64.0 
      taro-ui: 3.0.0-alpha.10 => 3.0.0-alpha.10 

这个 API 长什么样?

请问各位有没有一个完整的jest.config.js能借我参考一下,网上没有例子,让单元测试难以执行,希望能help me

@taro-bot2 taro-bot2 bot added the enhancement New feature or request label Jun 7, 2021
@zhiqingchen
Copy link
Member

哪个taro版本

@Saifa-96
Copy link
Author

Saifa-96 commented Jun 8, 2021

哪个taro版本

已经编辑更新taro版本信息

@zhiqingchen
Copy link
Member

@smoothdvd
Copy link
Contributor

https://github.com/NervJS/taro/blob/next/packages/taro-components-rn/jest.config.js

参考

@zhiqingchen 加入上述配置后,仍旧报错,有哪里需要修改吗?

···
$ jest
FAIL src/utils/test/httpclient.spec.ts
● Test suite failed to run

Jest encountered an unexpected token

This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.

By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".

Here's what you can do:
 • If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/en/ecmascript-modules for how to enable it.
 • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
 • If you need a custom transformation specify a "transform" option in your config.
 • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

You'll find more details and examples of these config options in the docs:
https://jestjs.io/docs/en/configuration.html

Details:

/home/alex/Dev/hznews-taro/node_modules/@tarojs/runtime/dist/runtime.esm.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import { injectable, inject, optional, multiInject, ContainerModule, Container } from 'inversify';
                                                                                         ^^^^^^

SyntaxError: Cannot use import statement outside a module

  at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1350:14)
  at Object.<anonymous> (node_modules/@tarojs/taro/index.js:1:132)

Test Suites: 1 failed, 1 total
Tests: 0 total
Snapshots: 0 total
Time: 2.686 s
···

babel.config.js:
···
// babel-preset-taro 更多选项和默认值:
// https://github.com/NervJS/taro/blob/next/packages/babel-preset-taro/README.md
module.exports = {
presets: [
['taro', {
framework: 'react',
ts: true
}]
]
}
···

@zhiqingchen
Copy link
Member

@iChengbo @shinken008

@smoothdvd
Copy link
Contributor

啊,原来jest-expo版本必须小于43

@zhiqingchen zhiqingchen added T-rn Target - 编译到 React Native V-3 Version - 3.x labels Nov 22, 2021
@smoothdvd
Copy link
Contributor

目前用如下配置可以跑通调用Taro.request的方法单元测试

// babel.config.js
// babel-preset-taro 更多选项和默认值:
// https://github.com/NervJS/taro/blob/next/packages/babel-preset-taro/README.md
module.exports = {
  presets: [
    [
      'taro',
      {
        framework: 'react',
        ts: true,
      },
    ],
    // 'module:metro-react-native-babel-preset',
    'babel-preset-expo',
    // '@babel/preset-env',
    // '@babel/preset-react',
  ],
  plugins: [
    ['@babel/plugin-proposal-private-property-in-object', { loose: true }],
    ['@babel/plugin-proposal-private-methods', { loose: true }],
    ['@babel/plugin-proposal-class-properties', { loose: true }],
  ],
  // env: {
  //   test: {
  //     plugins: ['@babel/plugin-transform-runtime'],
  //   },
  // },
};
// jest.config.js
module.exports = {
  ...require('jest-expo/jest-preset'),
  verbose: true,
  preset: 'react-native',
  transform: {
    // '^.+\\.(js|jsx|ts|tsx)$': '<rootDir>/node_modules/babel-jest',
    // '^. \\.js$': '<rootDir>/node_modules/react-native/jest/preprocessor.js',
    // '^.+\\.esm.js?$': 'ts-jest',
    // '^.+\\.(ts|tsx)$': 'ts-jest',
    '\\.[jt]sx?$': 'babel-jest',
  },
  // // modulePathIgnorePatterns: ['<rootDir>/TCRNExample'],
  moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
  coveragePathIgnorePatterns: ['/node_modules/'],
  // moduleNameMapper: {
  //   '^@/(.*)$': '<rootDir>/src/$1',
  // },
  moduleNameMapper: {
    '@tarojs/taro': '@tarojs/runtime-rn',
    // '@tarojs/components': '@tarojs/components-rn',
  },
  // testMatch: ['<rootDir>/src/__tests__/geolocation.test.js'],
  transformIgnorePatterns: [
    'node_modules/(?!(jest-)?@react-native|(jest-)?react-native|react-clone-referenced-element|@react-native-community|expo(nent)?|@expo(nent)?/.*|react-navigation|@react-navigation/.*|@unimodules/.*|sentry-expo|native-base)',
    // 'node_modules/(?!(@react-navigation|@tarojs/.*|@tarojs|react-native|@react-native|static-container|react-native-.*|@react-native-.*|expo-.*|@expo/.*|@unimodules/.*|unimodules-.*|@react-native-community/.*)/)',
  ],
  // setupFilesAfterEnv: ['./setup.js'],
  // testEnvironment: 'enzyme',
  // // testEnvironmentOptions: {
  // //   enzymeAdapter: 'react16',
  // // },
  testPathIgnorePatterns: ['/node_modules/'],
  // projects: [{ preset: 'jest-expo/android' }],
};
// src/utils/__tests__/httpclient.spec.ts
import Taro from '@tarojs/taro';
import Request from '../httpclient';

jest.mock('@tarojs/taro', () => ({
  request: jest.fn().mockResolvedValue({ data: { foo: 'bar' } }),
}));

const delay = async (ms = 50) => {
  return new Promise((resolve) => setTimeout(() => resolve(1), ms));
};

describe('Httpclient', () => {
  it('get request', async () => {
    const httpclient = new Request({ baseURL: 'https://localhost' });
    const args = {
      data: {},
      dataType: 'json',
      fail: expect.any(Function),
      header: {
        'Content-Type': 'application/json',
      },
      method: 'GET',
      success: expect.any(Function),
    };

    // mockRequest.mockResolvedValue({ data: 'test' });
    // httpclient.request = jest.fn().mockResolvedValue({ data: 'test' });
    httpclient.get('/test');
    await delay();
    expect(Taro.request).toHaveBeenCalledWith({
      ...args,
      baseURL: 'https://localhost',
      url: 'https://localhost/test',
    });
  });
});

"jest": "26.4.2",
"jest-expo": "^42.0.0",

配置参考了

@zhiqingchen @iChengbo @shinken008 @Saifa-96 是否正确,请指正。

@zhiqingchen
Copy link
Member

@smoothdvd 想问一下是否愿意给 taro rn 的相关接口和组件补充测试用例。

@smoothdvd
Copy link
Contributor

@zhiqingchen 可以,不过要等我手上的项目做完(顺带把taro-rn用熟)

@smoothdvd
Copy link
Contributor

@smoothdvd 想问一下是否愿意给 taro rn 的相关接口和组件补充测试用例。

目前用如下配置可以跑通调用Taro.request的方法单元测试

// babel.config.js
// babel-preset-taro 更多选项和默认值:
// https://github.com/NervJS/taro/blob/next/packages/babel-preset-taro/README.md
module.exports = {
  presets: [
    [
      'taro',
      {
        framework: 'react',
        ts: true,
      },
    ],
    // 'module:metro-react-native-babel-preset',
    'babel-preset-expo',
    // '@babel/preset-env',
    // '@babel/preset-react',
  ],
  plugins: [
    ['@babel/plugin-proposal-private-property-in-object', { loose: true }],
    ['@babel/plugin-proposal-private-methods', { loose: true }],
    ['@babel/plugin-proposal-class-properties', { loose: true }],
  ],
  // env: {
  //   test: {
  //     plugins: ['@babel/plugin-transform-runtime'],
  //   },
  // },
};
// jest.config.js
module.exports = {
 ...require('jest-expo/jest-preset'),
 verbose: true,
 preset: 'react-native',
 transform: {
   // '^.+\\.(js|jsx|ts|tsx)$': '<rootDir>/node_modules/babel-jest',
   // '^. \\.js$': '<rootDir>/node_modules/react-native/jest/preprocessor.js',
   // '^.+\\.esm.js?$': 'ts-jest',
   // '^.+\\.(ts|tsx)$': 'ts-jest',
   '\\.[jt]sx?$': 'babel-jest',
 },
 // // modulePathIgnorePatterns: ['<rootDir>/TCRNExample'],
 moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
 coveragePathIgnorePatterns: ['/node_modules/'],
 // moduleNameMapper: {
 //   '^@/(.*)$': '<rootDir>/src/$1',
 // },
 moduleNameMapper: {
   '@tarojs/taro': '@tarojs/runtime-rn',
   // '@tarojs/components': '@tarojs/components-rn',
 },
 // testMatch: ['<rootDir>/src/__tests__/geolocation.test.js'],
 transformIgnorePatterns: [
   'node_modules/(?!(jest-)?@react-native|(jest-)?react-native|react-clone-referenced-element|@react-native-community|expo(nent)?|@expo(nent)?/.*|react-navigation|@react-navigation/.*|@unimodules/.*|sentry-expo|native-base)',
   // 'node_modules/(?!(@react-navigation|@tarojs/.*|@tarojs|react-native|@react-native|static-container|react-native-.*|@react-native-.*|expo-.*|@expo/.*|@unimodules/.*|unimodules-.*|@react-native-community/.*)/)',
 ],
 // setupFilesAfterEnv: ['./setup.js'],
 // testEnvironment: 'enzyme',
 // // testEnvironmentOptions: {
 // //   enzymeAdapter: 'react16',
 // // },
 testPathIgnorePatterns: ['/node_modules/'],
 // projects: [{ preset: 'jest-expo/android' }],
};
// src/utils/__tests__/httpclient.spec.ts
import Taro from '@tarojs/taro';
import Request from '../httpclient';

jest.mock('@tarojs/taro', () => ({
 request: jest.fn().mockResolvedValue({ data: { foo: 'bar' } }),
}));

const delay = async (ms = 50) => {
 return new Promise((resolve) => setTimeout(() => resolve(1), ms));
};

describe('Httpclient', () => {
 it('get request', async () => {
   const httpclient = new Request({ baseURL: 'https://localhost' });
   const args = {
     data: {},
     dataType: 'json',
     fail: expect.any(Function),
     header: {
       'Content-Type': 'application/json',
     },
     method: 'GET',
     success: expect.any(Function),
   };

   // mockRequest.mockResolvedValue({ data: 'test' });
   // httpclient.request = jest.fn().mockResolvedValue({ data: 'test' });
   httpclient.get('/test');
   await delay();
   expect(Taro.request).toHaveBeenCalledWith({
     ...args,
     baseURL: 'https://localhost',
     url: 'https://localhost/test',
   });
 });
});

"jest": "26.4.2", "jest-expo": "^42.0.0",

配置参考了

@zhiqingchen @iChengbo @shinken008 @Saifa-96 是否正确,请指正。

babel-preset-expo预置配置要移到test环境中:

env: {
  test: {
    presets: ['babel-preset-expo'],
    plugins: ['@babel/plugin-transform-runtime'],
  },
},

@Chen-jj Chen-jj closed this as completed Apr 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request T-rn Target - 编译到 React Native V-3 Version - 3.x
Projects
None yet
Development

No branches or pull requests

4 participants