react-testing-library一般配置流程

1,311 阅读4分钟

前言

最近在学习使用React Testing Library,但是官方的安装和配置流程比较模糊,需要自己去Jest寻找做相应的配置,故本文用以记录一般的配置流程,其中包含babel、React、Typescript、CSS配置的解决。

若使用CRA(Create React App)创建的项目,则直接安装React Testing Library即可,本文记录的为非CRA创建项目。

项目初始化

此仓库是非CRA创建的项目:rtl-setup。你可以直接倒退到“init” commit后再跟随步骤进行

开始配置

第一步:安装Jest、React testing library

npm install --save-dev @testing-library/react jest

第二步:生成Jest配置

通过全局的Jest命令行,在项目下生成Jest配置。

先全局安装Jest

npm install -g jest

接着在对应项目下生成Jest配置

jest --init

根据自己需要选择选项即可

第三步:解决框架配置问题

这一步是比较多样化的,主要是对Jest的配置,需要根据项目状况来进行配置,比如是否使用了Typescript、是否已经配置好了babel。本文按照项目情况,根据babel、React、CSS Module、Typescript进行配置。

其中很多babel preset项目中可能已经安装好了,但为了流程流畅,本文中依然会将对应的preset列出。

babel配置

原项目中可能已有babel配置,若无,按照文档添加即可。

首先安装依赖:

npm install --save-dev babel-jest @babel/core @babel/preset-env

接着在babel.config.js中添加对应的presets:

// babel.config.js
module.exports = {
  presets: [['@babel/preset-env', {targets: {node: 'current'}}]],
};

后续React、Typescript的preset也需要在babel.config.js中进行相应的配置。

React配置

安装对应依赖

npm install --save-dev @babel/preset-react

对应的babel.config.js配置

// babel.config.js
module.exports = {
  presets: [['@babel/preset-env', {targets: {node: 'current'}}], '@babel/preset-react'],
};

typescript支持

Jest可以支持使用Typescript书写单元测试,只需要通过babel配置对应的Typescript preset即可,故安装对应的依赖:

npm install --save-dev @babel/preset-typescript

对应的babel.config.js配置

// babel.config.js
module.exports = {
  presets: [
    ["@babel/preset-env",{"targets": {"node": "current"}}], 
     "@babel/preset-react",
     "@babel/preset-typescript"
    ],
};

此后就可以用Typescript写单测了,书写单测的过程中若提示没有安装对应的types,按照提示安装即可。

Cannot find name 'describe'. Do you need to install type definitions for a test runner? Try `npm i --save-dev @types/jest` or `npm i --save-dev @types/mocha`.

这里仅需安装@types/jest。

CSS module

Jest本身不知道如何处理不同扩展的文件,对于CSS Module或者Less Module等,可以通过Jest的moduleNameMapper进行处理。

假设为进行相应的配置,直接引入css文件跑测试可能出现以下问题:

    SyntaxError: Unexpected token '.'

      1 | import React from 'react';
    > 2 | import './index.css';

官方也给出了相应的解决方案:使用ES6 Proxy来模拟CSS Modules。

首先安装identity-obj-proxy:

npm install --save-dev identity-obj-proxy

然后进行配置Jest的moduleNameMapper属性(在jest.config.js中或者package.json中)即可。

  moduleNameMapper: {
    "\\.(css|less)$": "identity-obj-proxy"
  }

testing-library/jest-dom配置

到目前为止我们的测试环境已经可以基本跑通,但是实际开发测试中还是不能满足的,比如需要判断一个元素是否在页面中需要用到APItoBeInTheDocument,如果这时没有配置jest-dom则会报错:expect(...).toBeInTheDocument is not a function,接下来就进行jest-dom的配置。

首先安装@testing-library/jest-dom:

npm install --save-dev @testing-library/jest-dom

接着创建setupTest.ts(或者setupTest.js)文件在src目录下(或者你喜欢的目录),写入代码:

import '@testing-library/jest-dom/extend-expect';

最后在jest.config.js中找到如下属性写入你的文件路径:

setupFilesAfterEnv: ['<rootDir>/src/setupTests.ts'],

如此便可顺利跑通。

其他可选配置

这部分的配置不是必须的,仅仅是个人在使用中发现的一些问题,可选进行

test.(js|ts)排除

Jest默认匹配的单元测试文件:

  • __tests__文件夹下的.js、.ts、.jsx、.tsx
  • .test.(js|ts|jsx|tsx)、.spec.(js|ts|jsx|tsx)
  • test.(js|ts|jsx|tsx)、spec.(js|ts|jsx|tsx)

由于某些开发者喜欢写test.js这样的文件名,但又不是单元测试,故个人想把诸如test.js此类无前缀的文件直接排除,只需要在jest配置的testMatch属性进行相应的修改。

testMatch属性是使用micromatch表示的,并非正则表达式,其默认值为:

testMatch:[ 
    "**/__tests__/**/*.[jt]s?(x)",
    "**/?(*.)+(spec|test).[jt]s?(x)"
]

根据micromatch文档,只需将\*\*/?(*.)中的·?改成+即可

testMatch: [
    "**/__tests__/**/*.[jt]s?(x)",
    "**/+(*.)+(spec|test).[tj]s?(x)"
],

测试

最后写一个示例组件与单测进行测试:

// test/example/Example.tsx

import React from 'react';
import './index.css';

const title = 'Hello React';

function Example() {
  return <div>{title}</div>;
}

export default Example;
// test/example/Example.test.tsx

import React from 'react';
import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom';
import Example from './Example';

describe('App', () => {
  test('renders App component', () => {
    render(<Example />);
    expect(screen.getByText('Hello React')).toBeInTheDocument();
  });
});

使用npm run test开始测试。

// package.json

 "scripts": {
    "test": "jest",
     ....

结果:

 PASS  test/example/Example.test.tsx
  App
     renders App component (22 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        1.194 s
Ran all test suites.

结语

经过以上配置,一个非CRA创建的React项目即可跑通Jest + React Testing Library,根据实际项目情况可适当做调整。

仓库地址:Joeoeoe/rtl-setup

参考资料

React Testing Library
Jest——additional-configuration
Jest——babel
Jest——React
Jest——Typescript
Jest——mocking css modules
Jest——testmatch-arraystring
syntaxerror with jest and react and importing css files
react testing library why is tobeinthedocument not a function
react-testing-library why is toBeInTheDocument() not a function