前端组件单选测试Jest + Enzyme

技术选型:Jest + Enzyme

Jest

www.jestjs.cn

Jest是Facebook开源的一个前端测试框架,主要用于React和React Native的单元测试,已被集成在create-react-app中。Jest特点:

  1. 易用性:基于Jasmine,提供断言库,支持多种测试风格

  2. 适应性:Jest是模块化、可扩展和可配置的

  3. 沙箱和快照:Jest内置了JSDOM,能够模拟浏览器环境,并且并行执行

  4. 快照测试:Jest能够对React组件树进行序列化,生成对应的字符串快照,通过比较字符串提供高性能的UI检测

  5. Mock系统:Jest实现了一个强大的Mock系统,支持自动和手动mock

  6. 支持异步代码测试:支持Promise和async/await

  7. 自动生成静态分析结果:内置Istanbul,测试代码覆盖率,并生成对应的报告

下面是一个使用Jest进行单元测试的例子:

javascript 复制代码
// sum.js
function sum(a, b) {
  return a + b;
}
module.exports = sum;

// sum.test.js
const sum = require('./sum');

test('adds 1 + 2 to equal 3', () => {
  expect(sum(1, 2)).toBe(3);
});

Enzyme

enzymejs.github.io/enzyme/

Enzyme是Airbnb开源的React测试工具库库,它功能过对官方的测试工具库ReactTestUtils的二次封装,提供了一套简洁强大的 API,并内置Cheerio,实现了jQuery风格的方式进行DOM 处理,开发体验十分友好。在开源社区有超高人气,同时也获得了React 官方的推荐。

下面是一个使用Enzyme进行单元测试的例子:

javascript 复制代码
import React from 'react';
import { shallow } from 'enzyme';
import MyComponent from './MyComponent';

describe('MyComponent', () => {
  it('renders correctly', () => {
    const wrapper = shallow(<MyComponent />);
    expect(wrapper).toMatchSnapshot();
  });

  it('increments the count when the button is clicked', () => {
    const wrapper = shallow(<MyComponent />);
    const button = wrapper.find('button');
    button.simulate('click');
    expect(wrapper.state('count')).toEqual(1);
  });
});

约定

推荐按照业界通用实践的规范,我们有如下约定:

  • 单元测试的代码放置在 tests 目录下
  • 单元测试文件命名格式使用 xxx.test.ts

相关配置

在项目根目录下创建jest.config.js文件,参数说明可以参考:jestjs.io/docs/en/con...

javascript 复制代码
module.exports = {
  // 块名称的映射关系
  moduleNameMapper: {
    '^#src/(.*)$': '<rootDir>/src/$1',
    '^@tencent/uno-ui': '<rootDir>/../../node_modules/@tencent/uno-ui-v2',
  },
  // 指定哪些文件不需要被收集代码覆盖率
  coveragePathIgnorePatterns: [
    '<rootDir>/.storybook/',
    '<rootDir>/.bin/',
    '<rootDir>/.build/',
    '<rootDir>/.build-docs/',
  ],
  // 指定需要收集代码覆盖率的文件
  collectCoverageFrom: ['src/**/*.{js,jsx,ts,tsx}'],
  // 指定在运行测试之前需要执行的脚本文件
  setupFilesAfterEnv: ['<rootDir>/src/test/setupTests.ts'],
  // 测试环境
  testEnvironment: 'jsdom',
  // 指定模块解析器,这里指定了一个自定义的解析器用于解决uuid库报错的问题
  resolver: `${__dirname}/src/test/resolver.js`,
};

遇到的问题

因为uuid只提供ESM浏览器导出,而不提供CommonJS导出出现了下面的报错,详情见下面的git链接
github.com/uuidjs/uuid...

javascript 复制代码
  /jest-bug/node_modules/uuid/dist/esm-browser/index.js:1
   ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){export { default as v1 } from './v1.js';
                                                                                     ^^^^^^

   SyntaxError: Unexpected token 'export'

   > 1 | import { v4 } from "uuid";
       | ^
     2 | import { nanoid } from "nanoid";
     3 |
     4 | export function getUuid() {

     at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1773:14)

解决办法

github.com/jestjs/jest...
github.com/microsoft/a...

javascript 复制代码
// https://github.com/jestjs/jest/issues/12770
// https://github.com/microsoft/accessibility-insights-web/pull/5421/commits/9ad4e618019298d82732d49d00aafb846fb6bac7
module.exports = (path, options) =>
  // Call the defaultResolver, so we leverage its cache, error handling, etc.
  options.defaultResolver(path, {
    ...options,
    // Use packageFilter to process parsed `package.json` before the resolution (see https://www.npmjs.com/package/resolve#resolveid-opts-cb)
    packageFilter: (pkg) => {
      // This is a workaround for https://github.com/uuidjs/uuid/pull/616
      //
      // jest-environment-jsdom 28+ tries to use browser exports instead of default exports,
      // but uuid only offers an ESM browser export and not a CommonJS one. Jest does not yet
      // support ESM modules natively, so this causes a Jest error related to trying to parse
      // "export" syntax.
      //
      // This workaround prevents Jest from considering uuid's module-based exports at all;
      // it falls back to uuid's CommonJS+node "main" property.
      //
      // Once we're able to migrate our Jest config to ESM and a browser crypto
      // implementation is available for the browser+ESM version of uuid to use (eg, via
      // https://github.com/jsdom/jsdom/pull/3352 or a similar polyfill), this can go away.
      if (pkg.name === 'uuid') {
        delete pkg.exports;
        delete pkg.module;
      }
      return pkg;
    },
  });

相关框架

ts-jest 是 Jest 的 TypeScript 预处理器。

@types/jest 和 @jest/types 是 Jest 的类型声明文件。

jest-environment-jsdom 是 Jest 的一个测试环境,用于在 Node.js 中模拟浏览器环境。

babel-jest 是 Jest 的一个预处理器,用于处理 ES6+ 语法。

enzyme 是一个流行的 React 组件测试工具。

enzyme-adapter-react-16 是适用于 React 16 版本的 Enzyme 适配器。

@types/enzyme 和 @types/enzyme-adapter-react-16 是 Enzyme 的类型声明文件

相关推荐
masa01019 分钟前
JavaScript--JavaScript基础
开发语言·javascript
让开,我要吃人了2 小时前
HarmonyOS开发实战(5.0)实现二楼上划进入首页效果详解
前端·华为·程序员·移动开发·harmonyos·鸿蒙·鸿蒙系统
everyStudy3 小时前
前端五种排序
前端·算法·排序算法
甜兒.4 小时前
鸿蒙小技巧
前端·华为·typescript·harmonyos
她似晚风般温柔7897 小时前
Uniapp + Vue3 + Vite +Uview + Pinia 分商家实现购物车功能(最新附源码保姆级)
开发语言·javascript·uni-app
Jiaberrr8 小时前
前端实战:使用JS和Canvas实现运算图形验证码(uniapp、微信小程序同样可用)
前端·javascript·vue.js·微信小程序·uni-app
everyStudy8 小时前
JS中判断字符串中是否包含指定字符
开发语言·前端·javascript
城南云小白8 小时前
web基础+http协议+httpd详细配置
前端·网络协议·http
前端小趴菜、8 小时前
Web Worker 简单使用
前端
web_learning_3218 小时前
信息收集常用指令
前端·搜索引擎