Next.js | Jest + React testing library + Typescript 单元测试框架搭建及实现

前言

单元测试和 E2E 测试作为 前端项目健壮性的保障,在许多团队可能并没有足够的能力和资源去实现很好的自动化测试,但基本的了解还是必不可少的。

最近在上手并集成单元测试到已有的 Next.js 项目中,网上的文档虽然很多,但实际使用的时候遇到的问题可谓五花八门,这篇文章可以帮助你快速的在 Next.js + TS 的环境中构建单元测试环境及进行单测的编写。

框架搭建

Jest 是目前最主流的前端测试框架,仅通过 Jest 没办法完成前端的所有单元测试,因为前端的单元测试涉及到 Dom 和事件的模拟。因此我们还需要一些测试辅助库来为我们模拟相关的场景。DOM Testing Library 适用于任何提供 DOM API 的环境,这个库提供了包含 ReactVue, Angular 这三个主流框架的 API,使用这些 API 我们可以在执行单测时实现 类似于用户在页面上查找元素 的方式查询 DOM 中的节点的操作,帮助我们实现更加符合真实环境的测试。

下面我们在已有的 Next.js 项目的基础上引入 JestReact testing library 以及相关的一些依赖,执行以下命令:

yarn add jest jest-environment-jsdom @testing-library/react @testing-library/jest-dom -D

接下来我们需要创建一下一下 Jest 的配置文件,在项目根目录下创建 jest.config.ts ,写入以下配置:

const nextJest = require('next/jest');

const createJestConfig = nextJest({
  // Provide the path to your Next.js app to load next.config.js and .env files in your test environment
  dir: './',
});

// Add any custom config to be passed to Jest
const customJestConfig = {
  // Add more setup options before each test is run
  // if using TypeScript with a baseUrl set to the root directory then you need the below for alias' to work
  moduleDirectories: ['node_modules', '<rootDir>/'],
  testEnvironment: 'jest-environment-jsdom',
  testPathIgnorePatterns: ['<rootDir>/cypress/'],
  setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1',
  },
};

// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
module.exports = createJestConfig(customJestConfig);

export {};

然后再创建 jest.setup.ts 文件,暂时先写入以下配置:

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

这个配置文件是根据 Next.js 文档中提供的配置进行修改的,我们先看看文档中对于这段配置的描述:

在后台,next/jest 会自动为我们配置 Jest,包括以下步骤:

  • 使用 SWC 设置 transform
  • 自动 mock 样式(包括.css.module.css 和它们的 scss 变量)、图片 import 以及 @next/font
  • 加载.env(所有的环境变量)到process.env
  • 在解析及编译测试时忽略 node_modules 目录
  • 在解析测试时忽略 .next 目录
  • 加载next.config.js用于启用 SWC transform 的配置

而我单独加的配置有如下几个:

  1. testPathIgnorePatterns: ['<rootDir>/cypress/']: 需要忽略的测试目录,这里我忽略了 cypres 目录,因为我们的 E2E 测试使用的是 Cypress ,如果不忽略的话,在执行 jest 的测试命令时会把 E2E 的测试也给跑起来。
  2. setupFilesAfterEnv: ['<rootDir>/jest.setup.ts']:配置 Jest 的 setup 文件位置,Jest 的 setup 文件用于在 执行测试时先执行一些固定的初始化操作,例如执行一些 import 等操作,这样就不需要在每一个测试中单独引入某些依赖了。
  3. moduleNameMapper: { '^@/(.*)$': '<rootDir>/src/$1', }:这一步是为了配置一下测试文件中 引入依赖时的别名,就像 webpack 或 vite 中 alias 配置的功能,当在引入依赖的目录中开头为 @ 时,会指向根目录下的 src 目录。
  4. 在配置文件的最后有一个 export {} ,这一步是为了解决当 tsconfig.json 中的 isolatedModules 设置为 true 时,如果 ts 文件中不存在
    importexport 时,ts 认为这个文件不是一个 ES Module,而是一个全局脚本,导致编译时报错。

接下来我们在 package.json 中新增一个指令:

"scripts": {
  //...
  "test": "jest"
}

当我们执行例如 yarn test 时,Jest 会去识别我们目录中的所有测试文件并执行。此时如果我们执行运行测试,会打印如下错误:

Error: Jest: Failed to parse the TypeScript config file

这个错误的原因是我们的配置文件是由 Node.js 去直接执行的,而 Node.js 并不能直接执行 ts 文件,我们也没有将配置文件进行编译,所以我们需要安装一下 ts-node,执行以下命令进行安装:

yarn add ts-node -D

安装后再次执行 yarn test 就不会报错了,ts-node 的作用就是让 Node.js 可以直接运行 ts 脚本,在执行的过程中自动进行编译,不需要我们自己提前编译为 js 脚本,更多详情可以参考 ts-node 官网

测试 Demo 编写

在框架搭建完成后,我们来实现一个简单的 demo 上手一下,首先我们需要设计一下测试的文件要放在哪个目录,这里我是将组件的测试目录与组件放在同一个目录中的,例如我们有一个 返回上一级的按钮组件 Back ,它的目录为 src/components/Back/index.tsx,这里我们再创建一个 src/components/Back/__test__ 目录用于放置测试文件,然后我们在目录中创建 index.test.tsx 文件,写入以下代码:

import { render, screen } from '@testing-library/react';

import Back from '../index';

describe('Back', () => {
  it('should render with default text', () => {
    render(<Back />);

    const element = screen.getByText(/back/i);

    expect(element).toBeInTheDocument();
  });

  it('should render with right test', () => {
    render(<Back text="Back to home" />);

    const element = screen.getByText(/Back to home/i);

    expect(element).toBeInTheDocument();
  });
});

describe 用于定义一个 测试用例组it 则用于定义一个 单独的测试用例,这两个 API 是全局定义的,并不需要引入。

代码中我们创建了一个测试用例组,其中包含了两个测试,it 的第一个参数用于描述测试的作用,这里就简单测试下 默认情况传入参数的情况 下组件是否能正确渲染。render 用于渲染组件,screen 大家可以理解为测试环境的 document,可以用于获取渲染的 dom 节点,expect 则是用于检查值是否满足特定条件。

因此这里的测试流程也就是:

  1. 引入并渲染组件
  2. 根据某些条件获取 dom 节点
  3. 判断组件是否正确渲染

后续更复杂的测试大致也是根据这种测试思路进行延伸,关于 API 的具体作用请参考 React-testing-library 文档Jest API 文档

配置 Github Action

在我们的测试可以顺利执行后,我们可以实现一下单测的自动化,这里以 Github Action
为例,基础的实现还是非常简单的,首先创建一个新的 workfolw 配置文件 your_project/.github/workflows/frontend-unit.yml

然后写入以下配置:

name: CI
on: push
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Install modules
      run: yarn
    - name: Run tests
      run: yarn test

这个配置文件就是在 ubuntu 环境中执行 yarn test 开始测试,当然在实际的项目中肯定不止这么简单,但根据实际情况进行触发时机的修改或增加执行流程即可,当然你也可以增加测试覆盖率的打印等命令,这个会在后面我实践后单独出文章介绍。

总结

这篇文章介绍了下如何在 Next.js 搭建组件测试的环境以及最基本的测试实现,关于更多的踩坑以及一些最佳实践会在后续摸索后继续出文章,如果大家对于 E2E 测试想要了解也可以评论区留言,在 E2E 测试方面我们已经有了比较丰富的实践经验,可以期待下后续的文章。如果这篇文章对你有帮助欢迎点赞或关注

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值