- 测试
- 开发工具
【免费下载链接】ts-jest
A Jest transformer with source map support that lets you use Jest to test projects written in TypeScript.
本篇指南基于 ts-jest 官方文档的 React Native 集成方案,讲解如何在 React Native + TypeScript + Babel 7 的项目中接入 Jest 测试。你将掌握三份核心配置(babel.config.js、tsconfig.spec.json、jest.config.ts)的编写方法,理解createJsWithBabelPreset背后的"TS 交给 ts-jest、JS 交给 babel-jest"双引擎原理,并学会用独立的 spec tsconfig 隔离测试编译环境。读完即可在自己的 RN 工程中复刻一套可直接运行的类型安全测试环境。
前置准备:先完成 React Native 官方 TypeScript 教程
ts-jest 官方文档(website/docs/guides/react-native.md)明确要求:在接入 ts-jest 之前,请先按照 React Native 官方博客中的 "Using TypeScript with React Native" 教程,将项目改造为 TypeScript 工程。该教程会帮你完成tsconfig.json与 Babel 7 的基础搭建。
完成上述改造后,你的工程中通常已具备以下前提:
- Babel 7 已配置,能够通过
babel.config.js加载 Metro 预设; tsconfig.json已存在,并设置了jsx等 JSX 编译选项;package.json中安装了typescript与@babel/core等依赖。
在此基础上,只需要三处"小改动"即可让 Jest + ts-jest 正常工作。下文按文档给出的顺序逐一展开。
第一步:Babel 配置——从.babelrc迁移到babel.config.js
文档给出的第一条改动:如果你还在使用.babelrc,请把 Babel 配置迁移到babel.config.js。原因在于 React Native 的测试场景中,Jest 与babel-jest都需要能够稳定地发现并加载 Babel 配置;babel.config.js是面向整个项目根目录的配置文件,比.babelrc(仅作用于其所在目录)更适合被 Jest 的模块解析机制查找。
配置文件内容至少需要包含 Metro 的预设:
module.exports = { presets: ['module:metro-react-native-babel-preset'], }module:metro-react-native-babel-preset是 React Native 官方提供的 Babel 预设,负责将 JSX、Flow(若使用)以及现代 JavaScript 语法转换为 React Native(Hermes / JavaScriptCore)运行时可以执行的代码。
在 ts-jest 的语境下,这份 Babel 配置还有第二层用途:它将被babelConfig: true选项所引用。ts-jest 默认不使用Babel(见 babelConfig 选项文档),但当babelConfig: true时,ts-jest 会依次查找项目中的.babelrc、.babelrc.js、babel.config.js或package.json中的babel字段,并把它交给babel-jest处理器执行。因此,将配置统一放在babel.config.js中,能让 ts-jest 稳定地找到它。
第二步:TypeScript 配置——为测试单独建立tsconfig.spec.json
文档要求在你的项目根目录新建一个tsconfig.spec.json:
{ "extends": "./tsconfig.json", "compilerOptions": { "jsx": "react" } }这份配置的作用是为测试环境派生一份独立的 TypeScript 编译配置:
extends: "./tsconfig.json":继承主工程的全部编译选项,避免重复维护;compilerOptions.jsx: "react":显式声明 JSX 的编译模式为经典React.createElement模式,确保测试文件中出现的.tsx组件能被正确编译为可在 Node/Jest 环境中执行的代码。
在 ts-jest 中,tsconfig选项(详见 tsconfig 选项文档)既可以指向一个 JSON 文件路径,也可以直接内联一个compilerOptions对象,甚至设为false以完全禁用 tsconfig 查找。这里通过tsconfig: 'tsconfig.spec.json'把测试编译与 App 编译(如 Metro 打包时使用的tsconfig.json)解耦,是文档推荐的隔离策略:生产构建与单元测试各自使用最适合自己的编译上下文。
第三步:Jest 配置——用createJsWithBabelPreset组装 transform
与迁移 Babel 配置同理,文档要求把 Jest 配置从package.json的jest字段迁移到独立的jest.config.ts,然后使用 ts-jest 提供的预设工厂函数组装 transform:
import type { Config } from 'jest' import { createJsWithBabelPreset } from 'ts-jest' const jsWithBabelPreset = createJsWithBabelPreset({ tsconfig: 'tsconfig.spec.json', babelConfig: true, }) const jestConfig: Config = { preset: 'react-native', transform: jsWithBabelPreset.transform, moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], } export default jestConfigcreateJsWithBabelPreset做了什么
从源码 src/presets/create-jest-preset.ts 可以看到,createJsWithBabelPreset返回的正是这样的 transform 映射:
export function createJsWithBabelPreset(tsJestTransformOptions: JsWithBabelTransformerOptions = {}): JsWithBabelPreset { logger.debug('creating JS with Babel CJS Jest preset') return { transform: { [JS_TRANSFORM_PATTERN]: 'babel-jest', [TS_TRANSFORM_PATTERN]: ['ts-jest', tsJestTransformOptions], }, } }其中两个正则常量定义在 src/constants.ts:
JS_TRANSFORM_PATTERN = '^.+\\.jsx?$':.js/.jsx文件交给babel-jest;TS_TRANSFORM_PATTERN = '^.+\\.tsx?$':.ts/.tsx文件交给ts-jest(携带tsconfig、babelConfig等选项)。
这正好对应了 React Native 工程的现实:.ts/.tsx源码中的类型注解与装饰器需要由 ts-jest 剥离,而.js/.jsx(包括 node_modules 中被引用的 JS 模块)则需要由babel-jest结合 Metro 预设完成转译。同一份 transform 对象中两套处理器各司其职,互不干扰。上述配置行为也有对应的单元测试验证,见 src/presets/create-jest-preset.spec.ts。
三个关键参数的取值说明
| 参数 | 含义 | 可选值 |
|---|---|---|
tsconfig | 指定测试使用的 TypeScript 编译配置 | false(禁用查找,使用 TS 默认选项);文件路径字符串(如'tsconfig.spec.json',相对于启动 Jest 的工作目录,支持<rootDir>);内联compilerOptions对象 |
babelConfig | 是否在 ts-jest 转译后追加 Babel 处理 | false(默认,不使用 Babel);true(自动查找.babelrc/.babelrc.js/babel.config.js/package.json的babel字段);内联 Babel options 对象(如{}表示不读取任何配置文件) |
| 正则键 | transform 的匹配模式 | 由预设工厂自动生成,无需手写 |
preset: 'react-native'是 Jest 官方为 React Native 提供的预设,负责解析 RN 特有的模块(如react-native包内的资源)与测试环境;moduleFileExtensions则显式声明了 Jest 在模块解析时按ts → tsx → js → jsx → json → node的顺序查找文件,确保.ts/.tsx文件在测试中能被正确命中。
双引擎转译链路:React Native 测试中的处理流程
综合以上配置,当 Jest 执行一个.tsx测试文件时,实际的处理链路如下:
- 匹配 transform:Jest 用
^.+\\.tsx?$命中文件,将其交给ts-jest处理器; - ts-jest 转译:读取
tsconfig.spec.json,剥离类型、按jsx: react编译 JSX,同时生成 source map,产出合法 JavaScript; - babel-jest 追加处理:因为
babelConfig: true,ts-jest 转译后的产物还会被送入babel-jest,加载babel.config.js中的module:metro-react-native-babel-preset完成面向 RN 运行时的进一步转译; - 执行测试:Jest 在 Node 运行时(或 jsdom 等自定义环境)中加载最终产物并运行断言。
对于测试文件中的.js/.jsx依赖,则直接由babel-jest处理,同样经过 Metro 预设。这种"TS 归 ts-jest、JS 归 babel-jest"的分工,与仓库中 examples/js-with-babel/jest.config.ts 示例的用法一脉相承:该示例同样调用createJsWithBabelPreset({ babelConfig: true }),并在 examples/js-with-babel/babel.config.js 中维护独立的 Babel 预设。
常见问题与注意事项
- 不要把 Babel 配置留在
.babelrc:Jest 的模块解析基于项目根目录展开,babel.config.js才能保证babelConfig: true稳定地发现配置; tsconfig.spec.json不要与主tsconfig.json混淆:测试文件通常需要不同的jsx模式或更宽松的编译选项,独立文件可以避免影响 Metro 的生产构建;babelConfig: true与babelConfig: {}的区别:前者会读取项目中的 Babel 配置文件,后者显式内联一个空配置、完全绕开文件查找(详见 babelConfig 选项文档)——在 React Native 场景中应使用前者,以复用 Metro 预设;- JSX 编译模式:若你的 RN 工程使用较新的 React 版本,可根据团队约定在 spec 配置中调整
jsx的值(如react-jsx),文档示例给出的react是兼容性最稳妥的选择。
小结
React Native + TypeScript 项目的 Jest 接入,本质上是把三条链路(Metro 的 Babel 预设、TypeScript 编译、Jest 模块解析)在测试环境下对齐。本文沿 ts-jest 官方指南的脉络,完成了babel.config.js迁移、tsconfig.spec.json隔离、jest.config.ts组装三步配置,并透过 create-jest-preset.ts 源码解释了createJsWithBabelPreset双引擎设计的底层逻辑。完成以上配置后,执行npx jest即可运行带类型检查与 source map 的 RN 测试套件。
- 测试
- 开发工具
【免费下载链接】ts-jest
A Jest transformer with source map support that lets you use Jest to test projects written in TypeScript.
相关推荐
PaddleSpeech VAD Android 端部署实战:实时语音活动检测的参数、用法与 JNI 引擎链路
PaddleSpeech VAD Android 端部署实战:实时语音活动检测的参数、用法与 JNI 引擎链路 本文以仓库中 VAD Android 示例说明
测试开发工具ts-jest 在 React Native 项目中的接入指南:TypeScript + Babel 7 的 Jest 配置实战
ts jest 在 React Native 项目中的接入指南:TypeScript + Babel 7 的 Jest 配置实战 本文基于 ts jest 官方
测试开发工具ts-jest 的 babelConfig 选项:在 TypeScript 编译后接入 Babel 转换的完整配置指南
ts jest 的 babelConfig 选项:在 TypeScript 编译后接入 Babel 转换的完整配置指南 导读 ts jest 默认完全不使用 B
测试开发工具
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考