Typescript and Jest
最近在折腾 typescript,把很多项目改成了 ts 的。有一个老项目,改的过程中感觉各种不踏实,打算还是先写点测试用例,就折腾了一下 jest。各种坑。。。
首先需要加一个 tsconfig.json
1{
2 "compilerOptions": {
3 "target": "es2015",
4 "module": "es2015",
5 "lib": [
6 "es2015"
7 ],
8 "outDir": "./lib",
9 "declaration": true,
10
11 "noEmit": true,
12 "moduleResolution": "node",
13 "esModuleInterop": true,
14 "allowSyntheticDefaultImports": true,
15
16 /* Strict Type-checking */
17 "strict": true,
18 "strictNullChecks": true,
19 "noImplicitAny": true,
20 "noImplicitThis": true,
21 "alwaysStrict": true,
22
23 /* Additional Checks */
24 "noUnusedLocals": true, /* Report errors on unused locals. */
25 "noUnusedParameters": true, /* Report errors on unused parameters. */
26 "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
27 "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
28 },
29 "include": [
30 "*.ts"
31 ],
32 "exclude": [
33 "node_modules",
34 "__tests__"
35 ]
36}
然后安装一个 typescript
就可以通过 yarn tsc
命令编译了,生成的 js 在 lib
下面。
测试如果是用 js 写,那么直接装 jest
就可以了。但是我们既然项目都改成 ts 了,那么还是希望用 ts 写。那就需要用到 ts-jest
。这货的配置可以写到 package.json
里面。
1{
2 "name": 'test-projct',
3 "version": "0.0.1",
4 ........
5 "jest": {
6 "preset": "ts-jest",
7 "testEnvironment": "node",
8 "testMatch": [ "**/__tests__/*-test.ts" ],
9 "globals": {
10 "ts-jest": {
11 "babelConfig": true,
12 "isolatedModules": true
13 }
14 }
15 }
16}
isolatedModules
表示说测试的时候先不做 type 检查。我这情况是,要改那些文件比较大一时都弄不好,可能 type 只改了部分,但是这个时候改到某个方法的时候,需要先加测试,以免改前改后不一致,所以这个时候只能忽略掉 type 检查了。
这样配置之后,就可以用 ts 写 test 了。test 文件放到 __tests__
目录里面,用 *-test.ts
命名。这样这目录也可以放一些非测试用文件了,比如测试用例用到的一些 mock 文件之类。
这样看着一切美好。直到我遇到了一个问题,我的那些需要测试的方法,有些是私有的,又不想因为这个改成 public 的,那么是不是有办法可以测试?这样就找到了 rewire
,这个可以把你的模块的内容随意替换组合,方便你做 mock。我要做的也覆盖了。这样完美了。
但是发现,rewire 不支持 typescript。在 ts 文件里面 rewire 一个模块之后,并没有多出来那些 __get__
和 __set__
方法。没仔细去研究代码,找到了 babel-plugin-rewire
,给 package.json
增加配置如下。
1 "babel": {
2 "presets": [
3 "env"
4 ],
5 "env": {
6 "test": {
7 "plugins": [
8 "babel-plugin-rewire"
9 ]
10 }
11 }
12 }
发现还是不行,并没有什么效果。查了之后发现,是因为 ts-test 根本不会去调用 babel 的缘故,所以上面的那个 babelConfig
就是这个用途,让 ts-test 去使用 babel。
目前还有一个问题是怎么让这个 package 在别人安装使用的时候自动编译为 js,这样让 js 用户也可以用。尝试过在 package.json
里面增加 build 发现不行。
1 "scripts": {
2 "build": "tsc",
3 "postinstall": "[ -f ../../node_modules/.bin/tsc ] && ../../node_modules/.bin/tsc || echo 'no typescript found, skip build'",
4 "test": "jest"
5 },
安装这个模块之后在 ./node_modules/test-module/
下面执行 tsc
并不会产出 lib
目录的编译文件。