如何使用jest测试koa?

为什么

自己写了一个网站,用作平时自己的导航页也写点小工具自己用,涉及到了后端内容,写了API,但是每次API测试都要自己手动用postman点点点,实在烦的不行,于是学了一点测试。

需求

对于我的API来说,没什么必要验证某个中间件是不是对的,能保证对应的请求能有正确的响应就可以了。所以也许应该叫,集成测试?端到端测试?也不是很清楚,还没学那么多呢

安装和配置

啥也不懂,随便抓了一个测试框架jest。因为Jest是一个令人愉快的 JavaScript 测试框架

1
yarn add -D jest

安装后就可以开始跑测试了。注意到我这里使用的是node不是浏览器,所以需要配置测试环境为node

1
2
3
4
// jest.config.js
module.exports = {
testEnvironment: 'node'
}

测试文件

jest默认会寻找项目中除node_modules之外所有的*.spec.js文件,将其作为测试运行。

我的应用也不大就把所有测试写在了一个文件里(好吧,其实是如果写多个文件那就好多测试一起跑,数据就乱掉了)。

文件语法可以看官方教程,基本逻辑很简单。

如何测试koa

首先说一下我项目中koa的逻辑

  • www:服务器的启动文件,不需要参与测试
  • app.js:定义了koa的应用,需要参与测试

koa

对于koa的测试可以使用supertest这个库,

1
2
3
4
5
6
7
8
9
// all.spec.js
const request = require('supertest')
test('basic authentication required', async () => {
const response = await request(app.callback()).get('/token')
expect(response.body).toEqual({
success: false,
message: 'basic authentication required'
})
})

引入后把他当作request用就可以了,除了目的是测试,用起来和直接发请求的感觉差不多。

process.env

由于测试时候只使用了koa应用本身,没有使用启动程序,所以我们需要自己搞定启动时候添加的process.env。方法和在启动文件中的一样,写在测试代码前面就可以了

1
2
3
4
// all.spec.js
// define process.env.*** in ./testpreset
require('./testpreset')
// then write test code

mongodb

这个真的,大坑!巨坑!。我是靠下面这三个解决的,看起来不优雅,但是确实可以工作了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// mongodb.js
// ...
const connect = async () => {
// connect database
if (process.env.NODE_ENV === 'test') {
// clear data in each Model
}
// run database init code
}
module.exports = { connect }

// all.spec.js
// ...
beforeAll(async () => {
await require('../src/utils/mongodb').connect()
})

afterAll(async () => {
await mongoose.connection.close()
})
// ...

// app.js
// ...
if (process.env.NODE_ENV !== 'test') { require('./utils/mongodb').connect() }
// ...

按顺序运行

You might want to use jest --runInBand to run the tests depending on how you structure your tests. Otherwise, multiple tests access same collection will cause random failing for your tests.
But thanks to one of the readers, Melroy van den Berg, I think you don’t need --runInBand if you open and close database connection with beforeEach and afterEach rather than the beforeAll and afterAll. Not tested, but it should be the root cause of the problem that I was encountering previously!

可视化

使用majestic

1
npm i majestic

然后在package.json中添加一条命令"testui": "npx majestic"

就可以运行了,运行之后会在浏览器打开ui界面。

参考