☰
Midway 3.x 单元测试实战指南:从 Jest 配置到 HTTP 与依赖注入测试
2026/10/10 1:55:09 网站建设 项目流程
  • 后端
  • 微服务
  • 云原生

【免费下载链接】midway

🍔 A Node.js Serverless Framework for front-end/full-stack developers. Build the application for next decade. Works on AWS, Alibaba Cloud, Tencent Cloud and traditional VM/Container. Super easy integrate with React and Vue. 🌈

项目地址:https://gitcode.com/gh_mirrors/mi/midway
点击查看免费下载

单元测试是保障 Node.js 应用稳定性的核心防线。Midway 3.x 在框架层面深度集成了 Jest 与@midwayjs/mock工具集,让开发者可以把精力集中在编写测试用例本身,而不是纠结于测试周边工具的选择与组装。本文将基于官方文档与仓库源码,系统讲解 Midway 3.x 应用测试的目录约定、运行工具、断言方式、HTTP 服务测试、依赖注入容器中的服务测试、createApp/close参数细节、bootstrap 入口测试,以及常见超时、串并行、编辑器调试等实战问题,帮助你建立一套完整、可复用的测试方法论。

测试目录结构与命名约定

Midway 约定test目录为存放所有测试脚本的目录,测试所使用到的fixtures(用于隔离测试的模拟应用目录)和相关辅助脚本都应该放在此目录下。

测试脚本文件统一按${filename}.test.ts命名,必须以.test.ts作为文件后缀。这样约定有两个直接好处:

  1. Jest 默认的testMatch规则可以直接识别测试文件;
  2. Midway 工具链在运行测试时会按\/test\/[^.]*\.test\.ts$/i的规则匹配测试套件(运行输出中的Ran all test suites matching /\/test\/[^.]*\.test\.ts$/i.即是证明)。

一个典型应用的测试目录示例:

➜ my_midway_app tree . ├── src ├── test │ └── controller │ └── home.controller.test.ts ├── package.json └── tsconfig.json

在仓库的各个包中,这一约定被严格遵守。例如 packages/web/test/custom.test.ts 就是按describe('/test/custom.test.ts', ...)组织,而测试所需的模拟应用全部放在各包的test/fixtures目录下(参见 packages/web/test/fixtures 中的base-app-use-custom-egg等项目)。

测试运行工具:midway-bin 与 jest

Midway 默认提供midway-bin命令来运行测试脚本。在新版本中,Midway 默认将 mocha 替换成了 Jest——Jest 功能更强大、集成度更高,让开发者聚焦精力在编写测试代码上,而不是纠结选择测试周边工具和模块。

只需要在package.json上配置好scripts.test即可,有两种方式可选:

方式一:直接使用 jest

{ "scripts": { "test": "jest" } }

方式二:使用 @midwayjs/cli(midway-bin)

{ "scripts": { "test": "midway-bin test --ts" } }

默认脚手架中都已经提供了上述命令,可以开箱即用地运行测试:

➜ my_midway_app npm run test > my_midway_project@1.0.0 test /Users/harry/project/application/my_midway_app > jest Testing all *.test.ts... PASS test/controller/home.controller.test.ts PASS test/controller/api.controller.test.ts Test Suites: 2 passed, 2 total Tests: 2 passed, 2 total Snapshots: 0 total Time: 3.26 s Ran all test suites matching /\/test\/[^.]*\.test\.ts$/i.

注意:midway-bin test --ts等价于直接使用 jest 的如下命令:

$ node --require=ts-node/register ./node_modules/.bin/jest

即通过ts-node/register让 Jest 在运行前先完成 TypeScript 的即时编译,这也是后续编辑器配置中反复出现这条命令的原因。

断言库:jest 内置的 expect

Jest 自带了强大的expect断言库,可以直接在全局使用它。常用的断言方法包括:

expect(result.status).toBe(200); // 值是否等于某个值,引用相等 expect(result.status).not.toBe(200); expect(result).toEqual('hello'); // 简单匹配,对象属性相同也为 true expect(result).toStrictEqual('hello'); // 严格匹配 expect(['lime', 'apple']).toContain('lime'); // 判断是否在数组中

其中toBe使用Object.is做引用相等比较,适合断言基本类型与引用身份;toEqual递归比较对象的结构与属性值;toStrictEqual比toEqual更严格,还会校验属性的类型与undefined属性等细节。

除了expect,Midway 官方测试示例中也常常混用 Node 内置的assert模块,例如仓库测试中的assert.deepStrictEqual(result.status, 200),两种断言风格可以按团队偏好混用。

创建测试:@midwayjs/mock 的核心方法

不同的上层框架的测试方法不同。以最常用的 HTTP 服务举例,测试一个 HTTP 服务,一般来说需要创建一个 HTTP 服务,然后用客户端请求它。

Midway 提供了一套基础的@midwayjs/mock工具集,帮助上层框架进行测试,同时提供方便的创建 Framework、App 以及关闭的方法。整个流程方法分为几个部分:

  • createApp创建某个 Framework 的 app 对象
  • close关闭一个 Framework 或者一个 app

为保持测试简单,整个流程目前只透出这两个方法。

// create app const app = await createApp<Framework>();

这里传入的Framework是用来给 TypeScript 推导类型的,这样就能返回主框架 app 实例了。

当 app 运行完成后,可以使用close方法关闭:

import { createApp, close } from '@midwayjs/mock'; await close(app);

事实上,createApp方法中封装了@midwayjs/bootstrap的启动逻辑。从 packages/mock/src/creator.ts 的源码可以看到,createApp的完整链路是:

  1. 先调用内部create<T>(baseDir, options),它会设置process.env.MIDWAY_TS_MODE(默认'true'),创建带 mock 过滤能力的DynamicMidwayContainer,再通过initializeGlobalApplicationContext完成全局应用上下文的初始化;
  2. 然后从容器中取出MidwayFrameworkService,调用getMainFramework()拿到主框架实例;
  3. 最后createApp再调用framework.getApplication()返回 app 实例。

在 packages/mock/src/index.ts 中,@midwayjs/mock对外导出了create、close、createApp、createFunctionApp、createLightApp、createBootstrap以及各类客户端方法(HTTP、Kafka、RabbitMQ、SocketIO、WS、SSE),说明 mock 工具集不仅覆盖 HTTP,还覆盖了消息队列与实时通信场景。

测试 HTTP 服务

除了创建 app 之外,@midwayjs/mock还提供了简单的客户端方法,用于快速创建各种服务对应的测试行为。

针对 HTTP,Midway 封装了 supertest,提供了createHttpRequest方法创建 HTTP 客户端:

// 创建一个客户端请求 const result = await createHttpRequest(app).get('/'); // 测试返回结果 expect(result.text).toBe('Hello Midwayjs!');

从源码看,packages/mock/src/client/http.ts 的实现非常精巧:createHttpRequest会优先取 app 的callback2或callback方法生成请求处理器,否则直接以 app 实例作为 supertest 的入参。这保证了它可以同时适配 Koa、Express、Egg 等不同底层框架的 app。

推荐在一个测试文件中复用 app 实例。完整的测试示例如下:

import { createApp, close, createHttpRequest } from '@midwayjs/mock'; import { Framework, Application } from '@midwayjs/koa'; import * as assert from 'assert'; describe('test/controller/home.test.ts', () => { let app: Application; beforeAll(async () => { // 只创建一次 app,可以复用 app = await createApp<Framework>(); }); afterAll(async () => { // close app await close(app); }); it('should GET /', async () => { // make request const result = await createHttpRequest(app) .get('/') .set('x-timeout', '5000'); // use expect by jest expect(result.status).toBe(200); expect(result.text).toBe('Hello Midwayjs!'); // or use assert assert.deepStrictEqual(result.status, 200); assert.deepStrictEqual(result.text, 'Hello Midwayjs!'); }); it('should POST /', async () => { // make request const result = await createHttpRequest(app) .post('/') .send({id: '1'}); // use expect by jest expect(result.status).toBe(200); }); });

这里的beforeAll/afterAll是 Jest 的生命周期钩子,beforeAll中只创建一次 app 并在afterAll中统一关闭,可以大幅降低反复启动框架的开销——这也是仓库各包测试(如 packages/web/test/custom.test.ts)普遍采用的模式。

HTTP 请求的常见参数传递

createHttpRequest(app)返回的是 supertest 实例,因此 supertest 的全部链式方法都可用:

创建 get 请求,传递 query 参数:

const result = await createHttpRequest(app) .get('/set_header') .query({ name: 'harry' });

创建 post 请求,传递 body 参数:

const result = await createHttpRequest(app) .post('/user/catchThrowWithValidate') .send({id: '1'});

创建 post 请求,传递 form body 参数:

const result = await createHttpRequest(app) .post('/param/body') .type('form') .send({id: '1'})

传递 header 头:

const result = await createHttpRequest(app) .get('/set_header') .set({ 'x-bbb': '123' }) .query({ name: 'harry' });

传递 cookie:

const cookie = [ "koa.sess=eyJuYW1lIjoiaGFycnkiLCJfZXhwaXIiOjE2MTQxNDk5NDk0NzIsIl9tYXhBZ2UiOjg2NDAwMDAwfQ==; path=/; expires=Wed, 24 Feb 2021 06:59:09 GMT; httponly", "koa.sess.sig=mMRQWascH-If2-BC7v8xfRbmiNo; path=/; expires=Wed, 24 Feb 2021 06:59:09 GMT; httponly" ] const result = await createHttpRequest(app) .get('/set_header') .set('Cookie', cookie) .query({ name: 'harry' });

.set()既可以传单个key, value,也可以传一个对象批量设置,还可以直接传'Cookie'数组。

测试服务:从依赖注入容器获取实例

在控制器之外,有时候需要测试单个服务,这时可以从依赖注入容器中获取这个服务。

假设需要测试UserService:

// src/service/user.ts import { Provide } from '@midwayjs/core'; @Provide() export class UserService { async getUser() { // xxx } }

那么在测试代码中这样写:

import { createApp, close, createHttpRequest } from '@midwayjs/mock'; import { Framework } from '@midwayjs/web'; import * as assert from 'assert'; import { UserService } from '../../src/service/user'; describe('test/controller/home.test.ts', () => { it('should GET /', async () => { // create app const app = await createApp<Framework>(); // 根据依赖注入 class 获取实例(推荐) const userService = await app.getApplicationContext().getAsync<UserService>(UserService); // 根据依赖注入 Id 获取实例 const userService = await app.getApplicationContext().getAsync<UserService>('userService'); // 传入 class 忽略泛型也能正确推导 const userService = await app.getApplicationContext().getAsync(UserService); // close app await close(app); }); });

这里app.getApplicationContext()返回应用的依赖注入容器,getAsync是异步获取实例的方法。Midway 默认按类名小驼峰生成对象标识(UserService→userService),所以按 Id 获取与按 class 获取结果一致;传入 class 时,TypeScript 可以从泛型推断返回类型,代码更简洁。

如果你的服务和请求相关联(即作用域为请求级,依赖ctx上下文),可以使用请求作用域获取服务——通过createAnonymousContext创建一个匿名上下文来模拟一次请求:

import { createApp, close, createHttpRequest } from '@midwayjs/mock'; import { Framework } from '@midwayjs/web'; import * as assert from 'assert'; import { UserService } from '../../src/service/user'; describe('test/controller/home.test.ts', () => { it('should GET /', async () => { // create app const app = await createApp<Framework>(); // 根据依赖注入 Id 获取实例 const userService = await app.createAnonymousContext() .requestContext.getAsync<UserService>('userService'); // 也能传入 class 获取实例 const userService = await app.createAnonymousContext() .requestContext.getAsync(UserService); // close app await close(app); }); });

需要说明的是,这里的@midwayjs/web对应仓库中的 Egg 上层框架实现,而@midwayjs/koa等其它框架的createApp用法完全一致——这正是createApp<Framework>()泛型设计的价值:不同框架之间测试代码的骨架可以无缝迁移。

createApp 选项参数

createApp方法用于创建一个框架的 app 实例,通过传入泛型的框架类型,使得推断出的 app 能够是该框架返回的 app。

比如:

import { Framework } from '@midwayjs/grpc'; // 这里的 app 能确保是 grpc 框架返回的 app const app = await createApp<Framework>();

createApp方法其实是有参数的,它的方法签名如下:

async createApp( appDir = process.cwd(), options: IConfigurationOptions = {} )
  • 第一个参数为项目的绝对根目录路径,默认为process.cwd()。注意,源码 packages/mock/src/creator.ts 中还有一层特殊处理:如果传入的不是绝对路径,会被拼接到process.cwd()/test/fixtures/下——这是为了支持直接传 fixtures 目录名(如createApp('feature/base-app'))的快捷写法;如果路径不存在会抛出MidwayCommonError。
  • 第二个参数为 Bootstrap 的启动参数,比如一些全局行为的配置。从 packages/mock/src/interface.ts 的MockBootstrapOptions定义可以看到,它继承自IMidwayBootstrapOptions与ILifeCycle,并额外支持:
参数说明
cleanLogsDir关闭后是否清理 logs 日志目录
cleanTempDir是否清理临时目录(如 egg 生成的 run 目录)
ssl是否以 HTTPS 启动(@midwayjs/mock自带ssl/ssl.key与ssl/ssl.pem证书文件,见 packages/mock/ssl)
bootstrapTimeoutbootstrap 入口启动超时时间,默认 30 秒
entryFile入口文件路径(如bootstrap.js)
bootstrapMode'faas'或'app'两种模式
moduleLoadType'commonjs'或'esm',根据package.json的type字段自动推断
onReady/onStop/onConfigLoad/onServerReady/onHealthCheck生命周期钩子回调

另外,create内部还会自动处理MIDWAY_TS_MODE环境变量(默认置为'true'),这意味着在 TypeScript 测试环境中,源码和测试文件都会走 ts-node 的即时编译通道。

close 选项参数

close方法用于关闭该 app 实例相关的框架:

await close(app);

其签名如下:

export declare function close( app: IMidwayApplication | IMidwayFramework<any, any>, options?: { cleanLogsDir?: boolean; cleanTempDir?: boolean; sleep?: number; }): Promise<void>;
  • 第一个参数是 app 或者 framework 的实例。
  • 第二个参数是个对象,在执行关闭时可以执行一些行为:
  1. cleanLogsDir:默认为false,控制测试完成后删除日志 logs 目录(windows 除外);
  2. cleanTempDir:默认为false,清理一些临时目录(比如 egg 生成的 run 目录);
  3. sleep:默认为50,单位毫秒,关闭 app 后的延迟时间(防止日志没有成功写入)。

从源码 packages/mock/src/creator.ts 可以看到close的完整行为:它会先调用destroyGlobalApplicationContext销毁全局应用上下文,然后仅在isTestEnvironment()(即MIDWAY_SERVER_ENV/EGG_SERVER_ENV/NODE_ENV为test或unittest之一)时执行清理与休眠逻辑。此外,close还兼容了BootstrapAppStarter这类具备close方法但没有getConfig的启动器对象。

使用 bootstrap 文件测试

一般情况下,无需用到bootstrap.js来测试。如果你希望直接使用bootstrap.js入口文件直接测试,可以在测试的时候传递入口文件信息。

和 dev/test 启动不同的是,使用bootstrap.js启动是一个真实的服务,会同时运行多个框架,创建出多个框架的 app 实例。

@midwayjs/mock提供了createBootstrap方法做启动文件类型的测试。我们可以将入口文件bootstrap.js作为启动参数传入,这样createBootstrap方法会通过入口文件来启动代码:

it('should GET /', async () => { // create app const bootstrap = await createBootstrap(join(process.cwd(), 'bootstrap.js')); // 根据框架类型获取 app 实例 const app = bootstrap.getApp('koa'); // expect and test // close bootstrap await bootstrap.close(); });

从 packages/mock/src/creator.ts 的实现看,createBootstrap会先检测工作目录是否安装了@midwayjs/faas,据此自动选择'faas'或'app'模式;在'app'模式下,它通过entryFile触发真实的 bootstrap 启动(源码中会轮询MIDWAY_BOOTSTRAP_APP_READY全局标志,每 200ms 检查一次,直到Bootstrap.ready完成或bootstrapTimeout超时),最后返回一个BootstrapAppStarter。这个启动器通过MidwayApplicationManager按框架类型(如'koa')取出对应 app,关闭时则调用@midwayjs/bootstrap的Bootstrap.stop()。

运行单个测试

和 mocha 的only不同,jest 的only方法只针对单个文件生效。

方式一:直接使用 jest

执行单个文件:

$ jest test/controller/api.ts

如果你想运行文件中的特定测试,可以使用 jest 的-t或--testNamePattern选项,后面跟上你想运行的测试的名称:

$ jest -t "name of your test"

这将只运行名称匹配的测试。

方式二:使用 @midwayjs/cli

midway-bin提供运行单个文件的能力:

$ midway-bin test -f test/controller/api.ts

这样可以指定运行某个文件的测试,再配合describe.only和it.only,可以只运行单个文件中的单个测试方法。

自定义 Jest 文件内容

一般情况下,Midway 工具链内置了 jest 配置,用户无需再添加该文件。但有些特殊场景下,比如使用 VSCode 或 Idea 等编辑器,需要在可视化区域进行开发和测试时,可能会需要指定一个jest.config.js的场景,此时 Midway 支持创建一个自定义的 jest 配置文件。

在项目根目录创建一个jest.config.js文件:

➜ my_midway_app tree . ├── src ├── test │ └── controller │ └── home.test.ts ├── jest.config.js ├── package.json └── tsconfig.json

内容如下,配置和标准的 jest 相同:

module.exports = { preset: 'ts-jest', testEnvironment: 'node', testPathIgnorePatterns: ['<rootDir>/test/fixtures'], coveragePathIgnorePatterns: ['<rootDir>/test/'], };

关键配置项说明:

  • preset: 'ts-jest':让 Jest 使用 ts-jest 完成 TypeScript 编译;
  • testEnvironment: 'node':运行环境为 Node(而非 jsdom),因为 Midway 是纯服务端框架;
  • testPathIgnorePatterns: ['<rootDir>/test/fixtures']:非常重要,fixtures 目录是测试专用的模拟应用,必须排除在测试匹配之外,否则会被当作测试套件执行;
  • coveragePathIgnorePatterns: ['<rootDir>/test/']:覆盖率统计时忽略测试目录本身。

在仓库中,每个包都自带jest.config.js与jest.setup.js,例如 packages/web/jest.config.js、packages/core/jest.config.js,可以参考其实际写法。

常见设置:jest.setup.js 与四个经典问题

如果需要在单测前执行一些代码,可以增加jest.setup.js,配置如下:

const path = require('path'); module.exports = { preset: 'ts-jest', testEnvironment: 'node', testPathIgnorePatterns: ['<rootDir>/test/fixtures'], coveragePathIgnorePatterns: ['<rootDir>/test/'], setupFilesAfterEnv: ['<rootDir>/jest.setup.js'], // 预先读取 jest.setup.js };

:::caution 注意,jest.setup.js只能使用 js 文件。 :::

setupFilesAfterEnv中的文件会在每个测试文件执行前被加载,适合放置全局的初始化逻辑。下面结合官方文档,给出四个最常见的实战问题与解法。

示例一:测试代码时间较长的问题

如果测试出现下面的错误,说明你的代码执行时间比较长(比如连接数据库、跑任务等)。如果确定代码没有问题,就需要延长启动时间:

Timeout - Async callback was not invoked within the 5000 ms timeout specified by jest.setTimeout.Error: Timeout - Async callback was not invoked within the 5000 ms timeout specified by jest.setTimeout.

jest 默认时间为5000ms(5 秒钟),可以调整到更多。可以通过在package.json启动时修改:

{ "scripts": { "test": "jest --testTimeout=30000" } }

或者使用 midway-bin:

{ "scripts": { "test": "midway-bin test --ts --testTimeout=30000" } }

这里的testTimeout是 jest 的启动参数。也可以在jest.setup.js文件中写入下面的代码,对 jest 超时时间做调整:

// jest.setup.js jest.setTimeout(30000);

示例二:全局环境变量

同理,jest.setup.js也可以执行自定义的代码,比如设置全局环境变量:

// jest.setup.js process.env.MIDWAY_TS_MODE = 'true';

这个变量本身是 Midway 识别 TypeScript 测试环境的关键开关——@midwayjs/mock的create方法中process.env.MIDWAY_TS_MODE = process.env.MIDWAY_TS_MODE ?? 'true'(见 packages/mock/src/creator.ts),在jest.setup.js中显式设置可以确保即便不经过 mock 工具链,环境变量也始终生效。

示例三:程序无法正常退出的处理

有时候,由于一些代码(定时器、监听等)在后台运行,导致单测跑完后会无法退出进程。对于这个情况,jest 提供了--forceExit参数:

$ jest --forceExit $ jest --coverage --forceExit

使用 midway-bin 时:

$ midway-bin test --ts --forceExit $ midway-bin cov --ts --forceExit

也可以在自定义 jest 配置文件中增加forceExit属性:

module.exports = { preset: 'ts-jest', testEnvironment: 'node', testPathIgnorePatterns: ['<rootDir>/test/fixtures'], coveragePathIgnorePatterns: ['<rootDir>/test/'], forceExit: true, };

注意:--forceExit是强制退出,本质上是绕过未关闭的句柄直接结束进程,属于兜底方案。更好的做法是先排查并主动清理定时器、关闭服务或断开数据库连接。

示例四:并行改串行执行

jest 默认为每个测试文件并行处理。如果测试代码中有启动端口等场景,并行处理可能会导致端口冲突而报错,这个时候需要加--runInBand参数。注意,这个参数只能加在命令中(无法在jest.config.js中配置):

$ jest --runInBand $ jest --coverage --runInBand

使用 midway-bin 时:

$ midway-bin test --ts --runInBand $ midway-bin cov --ts --runInBand

--runInBand让所有测试文件在当前进程中串行执行,虽然会牺牲一些速度,但能彻底规避端口与资源竞争问题。也可以与--forceExit组合使用。

编辑器配置

Jetbrains Webstorm/Idea 配置

在 Jetbrains 的编辑器使用,需要启用 "jest" 插件。由于使用了子进程的方式启动,依旧需要在启动时指定加载--require=ts-node/register。

在 Run/Debug Configurations 中新增 Jest 配置,Jest options 中填入:

node --require=ts-node/register ./node_modules/.bin/jest

这样 Jest 运行子进程时会先经过 ts-node 编译 TypeScript,与命令行midway-bin test --ts的效果一致。

VSCode 配置

先搜索并安装 Jest Runner 插件。打开配置,配置 jest 命令路径——在 jest command 处填入:

node --require=ts-node/register ./node_modules/.bin/jest

或者在工作区文件夹.vscode里面设置settings.json:

{ "jest.pathToJest": "node --require=ts-node/register ./node_modules/.bin/jest --detectOpenHandles", "jestrunner.jestCommand": "node --require=ts-node/register ./node_modules/.bin/jest --detectOpenHandles" }

其中--detectOpenHandles会在测试结束后列出未关闭的句柄(定时器、socket 等),对排查"进程无法退出"的问题很有帮助。

由于 jest runner 插件的调试使用的是 VSCode 的调试,需要单独配置 VSCode 的launch.json。在文件夹.vscode里面设置:

{ "version": "0.0.1", "configurations": [ { "name": "Debug Jest Tests", "type": "node", "request": "launch", "runtimeArgs": [ "--inspect-brk", "--require=ts-node/register", "${workspaceRoot}/node_modules/.bin/jest", "--runInBand", "--detectOpenHandles" ], "console": "integratedTerminal", "internalConsoleOptions": "neverOpen" } ] }

这里--inspect-brk会在启动时暂停等待调试器附加,--runInBand确保串行执行便于单步调试。

关于 alias paths

需要注意,mwtsc工具不支持 Alias Path 功能。因此在使用路径别名(如@/service/user)时,需要自行在 jest 配置中增加moduleNameMapper映射,或尽量避免在测试代码中依赖路径别名,保持相对路径引用,才能与mwtsc的编译链路完全兼容。

关于 mock 数据

模拟数据是一个可以在开发和测试中都通用的能力。@midwayjs/mock不仅在启动与请求层面提供支持,还封装了完整的 mock 数据 API(见 packages/mock/src/mock.ts):

  • mockSession(app, key, value):为请求上下文 mock 一个 session 字段;
  • mockHeader(app, headerKey, headerValue):mock 请求头;
  • mockContext(app, key, value):mock 上下文属性或行为;
  • mockClassProperty(clzz, propertyName, value)/mockProperty(obj, key, value):mock 类属性与对象属性;
  • restoreAllMocks()/restoreMocks(group):统一恢复被 mock 的内容。

这些能力底层的实现统一委托给@midwayjs/core的MidwayMockService,通过分组(group,默认'default')管理,可以在afterAll或afterEach中调用restoreAllMocks()恢复现场,避免 mock 污染影响后续用例。更多细节可参考仓库的 模拟数据文档。

小结

Midway 3.x 的测试体系可以用一句话概括:约定目录结构 + Jest 运行器 +@midwayjs/mock一站式工具集。在实际项目中,建议遵循以下实践清单:

  1. 测试文件统一放在test目录,按${name}.test.ts命名,fixtures一律置于test/fixtures下并在 jest 配置中排除;
  2. 优先使用脚手架自带的npm test,直接使用 jest 或midway-bin test --ts均可,二者对 TypeScript 的支持等价;
  3. 每个测试文件通过beforeAll创建一次 app、afterAll统一close,复用 app 实例提升效率;
  4. HTTP 测试用createHttpRequest(app)链式构造请求,覆盖 query、body、form、header、cookie 各种参数形态;
  5. 服务测试通过app.getApplicationContext().getAsync()获取单例,请求级服务用createAnonymousContext().requestContext获取;
  6. 遇到超时、进程不退出、端口冲突等问题,分别用--testTimeout、--forceExit、--runInBand对症解决;
  7. 编辑器场景下配置好 ts-node 启动命令,即可获得可视化的测试运行与调试体验。

掌握这套方法论后,无论是控制器、服务还是多框架混合应用,都能写出稳定、高效、可维护的单元测试,为应用质量兜底。

  • 后端
  • 微服务
  • 云原生

【免费下载链接】midway

🍔 A Node.js Serverless Framework for front-end/full-stack developers. Build the application for next decade. Works on AWS, Alibaba Cloud, Tencent Cloud and traditional VM/Container. Super easy integrate with React and Vue. 🌈

项目地址:https://gitcode.com/gh_mirrors/mi/midway
点击查看免费下载
上一篇:CodeContracts部署指南:从源码构建到生产环境配置
下一篇:30亿参数逆袭130亿模型:阿里WebSailor-3B改写开源智能体格局

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询