前言
Nestjs作为当下对TypeScript支持最好的后端框架之一(可能没有之一),被越来越多的人使用.
最近自己也在学习和使用中,这其中也踩了不少坑,尤其是在和数据库连接的测试中.
这篇文章主要介绍如何使用Docker配合单元测试
测试的三种方法
- 使用mock,对返回值进行mock,不直接和数据库进行交互
- 使用内存数据库/磁盘数据库.例如Sqlite.
- 利用docker增加测试数据库,在测试是开启docker内的数据库服务
三种方式的优缺点
方法 | 优点 | 缺点 |
---|---|---|
使用mock | 更加灵活,和数据库进行了隔离 | 写法麻烦且难维护;没有和数据库真实产生交互 |
使用内存数据库/磁盘数据库 | 和数据库产生真实交互,容易维护 | postgresql的很多特性,内存数据库其实并不支持 |
利用Docker | 对你实际使用的数据库类型进行测试 | 复杂度和开销比较大 |
利用Docker增加测试数据库
以上三种方式,在项目中都使用过,根据实际情况,我最终选择了第三种方法:利用Docker增加测试数据库
思路
每次在跑测试之前,开启Docker
启动相应的数据库服务,并初始化数据库;单元测试结束之后,移除数据库,关闭Docker
服务.
安装Docker
大家可以参考这个去安装 https://www.runoob.com/docker/ubuntu-docker-install.html
配置docerk-compose
version: "3"
services:
test-db:
image: postgres
restart: always
ports:
- "5433:5432"
environment:
POSTGRES_PASSWORD: xxx
volumes:
- ./test/init.sql:/docker-entrypoint-initdb.d/init.sql #初始化测试数据库
方法一: 通过npm
启动
"posttest": "docker-compose stop test-db && docker-compose rm -f test-db", //测试结束后关闭docker并移除服务
"pretest": "docker-compose up -d test-db" //测试开始前开启dcoker和服务
###方法二: 配置jest
npm 启动的方式,无法在IDE内单独执行某个测试,所以我开始对jest进行配置
用setup和globalTeardown在测试开始前和结束后,启动/关闭 docker
//setup.ts
const { execSync } = require('child_process');
export default async function() {
execSync('docker-compose up -d test-db');
}
//globalTeardown.ts
const { execSync } = require('child_process');
export default async function() {
execSync('docker-compose stop test-db && docker-compose rm -f test-db');
}
//jest.json
"globalSetup": "./test/setup.ts",
"globalTeardown": "./test/globalTeardown.ts"
小结
以上就是最近对Nestjs测试的实践.这三种方式对其他Node项目应该也是一样的.如果项目需要集成Redis
或者其他服务,都可以通过Docker
进行配置
SQLite创建的数据库有一种模式IN-MEMORY,但是它并不表示SQLite就成了一个内存数据库。IN-MEMORY模式可以简单地理解为,本来创建的数据库文件是基于磁盘的,现在整个文件使用内存空间来代替磁盘空间,其它操作保持一致。也就是数据库的设计没有根本改变。
无法在IDE内单独执行某个测试,是这样么?
@i5ting 嗯嗯,是的.这个地方描述的确实不太准确.我们项目中一直使用的是IN-MEMORY模式. 谢谢大佬指出.
@i5ting 如果我只配置了npm的话,是没办法在WebStrom
中通过IDE点击来执行某个单独的测试的.因为IDE跑jest测试的时候走的是jest的配置,所以后面我又弄的jest启动的时候开启Docker
. 还请大佬多多指教.是不是可以有继续优化的地方
vscode里是断点打到测试用例上的,jest跑的时候也是可以单个测试执行或watch的。可以玩的点还是非常多的。
@i5ting 如果我只加了npm的那个script我没办法点击某个测试用例执行的时候,运行docker. 所以我弄了jest的globalSetup和globalTeardown. 这个方案是我们第一次在一个项目中使用,也不知道对不对.