close

从 Jest 迁移

Rstest 提供兼容 Jest 的 API,这使得从 Jest 项目迁移变得简单。以下是如何将你的 Jest 项目迁移到 Rstest:

使用 Agent Skills

如果你在使用支持 Skills 的 Coding Agent,可以安装 migrate-to-rstest 技能来辅助完成从 Jest 到 Rstest 的迁移。

npx skills add rstackjs/agent-skills --skill migrate-to-rstest

安装后,让 Coding Agent 协助完成升级即可。

安装依赖

首先,你需要安装 Rstest 依赖。

npm
yarn
pnpm
bun
deno
npm add @rstest/core -D

接下来,更新 package.json 中的测试脚本,使用 rstest 替代 jest。例如:

"scripts": {
-  "test": "jest"
+  "test": "rstest"
}

配置迁移

将你的 Jest 配置文件(例如 jest.config.jsjest.config.ts)更新为 rstest.config.ts 文件:

rstest.config.ts
import { defineConfig } from '@rstest/core';

export default defineConfig({
  globals: true,
});

Jest 配置映射

以下是一些常见的 Jest 配置及其对应的 Rstest 配置:

Jest 配置Rstest 对等配置
testRegexinclude
testMatchinclude
testPathIgnorePatternsexclude
transformIgnorePatternsoutput.externalssource.exclude
displayNamename
rootDirroot
setupFilesAfterEnvsetupFiles
verboseverbose-reporter
injectGlobalsglobals
moduleNameMapperresolve.alias
maxWorkerspool.maxWorkers
collectCoveragecoverage.enabled
coverageDirectorycoverage.reportsDirectory
coverageProvidercoverage.provider
coveragePathIgnorePatternscoverage.exclude
coverageThresholdcoverage.thresholds

更多详情,请参考 配置文档

注入全局 API

与 Jest 不同,Rstest 默认不会将测试 API(如 describeexpectittest)挂载到全局对象上。

如果你希望继续使用全局测试 API,可以在 rstest.config.ts 文件中启用 globals 选项:

rstest.config.ts
import { defineConfig } from '@rstest/core';

export default defineConfig({
  globals: true,
});

为了让 TypeScript 正确识别这些全局 API,请在 tsconfig.json 中添加 @rstest/core/globals 类型声明:

tsconfig.json
{
  "compilerOptions": {
    "types": ["@rstest/core/globals"]
  }
}

代码转换

Rstest 默认使用 swc 进行代码转换,这与 Jest 的 babel-jest 不同。大多数情况下,你不需要做任何更改。你可以通过 tools.swc 配置你的 swc 选项。

export default {
-  transform: {
-    '^.+\\.(t|j)sx?$': ['@swc/jest', {}],
-  },
+  tools: {
+    swc: {}
+  }
}

如果你有自定义的 Babel 配置或使用特定的 Babel 插件/预设,你可以添加 Rsbuild Babel 插件

rstest.config.ts
import { pluginBabel } from '@rsbuild/plugin-babel';
import { defineConfig } from '@rstest/core';

export default defineConfig({
  plugins: [pluginBabel()],
});

更新测试 API

测试 API

Rstest 提供了与 Jest 兼容的 API。因此,你只需将导入从 Jest 更改为 Rstest:

- import { describe, expect, it, test } from '@jest/globals';
+ import { describe, expect, it, test } from '@rstest/core';

Rstest 提供了 rstest API,你可以使用它来访问 Rstest 的工具函数,如 rstest.fn()rstest.mock()。就像 Jest 的 jest.fn()jest.mock() 一样。更多工具函数可以在 Rstest APIs 中找到。

- const fn = jest.fn();
+ const fn = rstest.fn();

fn.mockResolvedValue('foo');

Done 回调

Rstest 不支持 done 回调。作为替代,你可以返回一个 Promise 或使用 async/await 进行异步测试。

- test('async test with done', (done) => {
+ test('async test with done', () => new Promise(done => {
  // ...
  done();
- });
+ }));

如果你需要处理错误,你可以按照以下方式修改:

- test('async test with done', (done) => {
+ test('async test with done', () => new Promise((resolve, reject) => {
+   const done = err => (err ? reject(err) : resolve());
  // ...
  done(error);
- });
+ }));

Hooks

Rstest 中 beforeEachbeforeAll 钩子的返回函数用于执行测试后的清理工作。

- beforeEach(() => doSomething());
+ beforeEach(() => { doSomething() });

超时设置

如果你使用 jest.setTimeout() 来设置测试的超时时间,你可以改用 rstest.setConfig()

- jest.setTimeout(5_000)
+ rstest.setConfig({ testTimeout: 5_000 })

ESM 和 CJS

Rstest 默认支持 ESM。如果你的项目使用 ESM,你不需要进行任何额外配置(例如设置 NODE_OPTIONS=--experimental-vm-modules)。

如果你的项目仍在使用 CommonJS,Rstest 仍然可以正常工作,但我们建议迁移到 ESM,以获得更好的性能和未来的兼容性。

ESM vs CJS mocking

在 Rstest 中,rstest.mock() 针对 import 使用的 ESM 入口,而 rstest.mockRequire() 针对 require() 使用的 CJS 入口。

如果你的代码使用了 require(),你应该使用 rstest.mockRequire() 来确保 Mock 了正确的入口:

// Mock 一个 CJS 模块
rstest.mockRequire('./math.cjs', () => ({
  sum: (a, b) => a + b + 100,
}));