在本文中,我将向您展示如何测试快速效果和MongoDB应用程序!
请注意,这篇文章是"How to use Fastify and MongoDb"article的随访,您学会了如何创建CRUD应用程序。
什么样的测试?
我们必须说它存在世界上很多测试:
- 单元测试:编写的测试以测试一个单元的代码。
- 集成测试:编写以测试整个应用程序的测试。
- 最终测试:编写的测试以测试从客户端到服务器端的整个应用程序。
- UI测试:编写用于测试应用程序用户界面的测试。
- 性能测试:编写以测试应用程序性能的测试。
- 安全测试:编写以测试应用程序安全性的测试。
- 烟雾测试:编写以简单方式测试应用程序的测试。
- 压力测试:以压力性的方式编写以测试应用程序的测试。
我认为我可以继续列出几个小时的所有测试。
如果您想深入研究,可以阅读Martin Fowler's网站。它包含许多有关测试的文章。
现在,我们将专注于集成测试。
我选择编写集成测试,因为我认为:
- 您可以专注于应用程序的业务逻辑。
- 在码头环境中,旋转容器便宜且容易。
- 测试代码较少:您也不需要模拟和修复模拟。
- 将您在生产中的一些错误结晶很有帮助。
可以肯定的是,添加单元测试是一种很好的方法,但我通常会为特定组件做。我们将在本文末尾看到一个示例。
选择正确的测试框架
fastify具有a koude0 methodthat允许您在不启动HTTP服务器的情况下向应用程序注入请求。
koude1测试框架中的此功能使您可以更快地测试应用程序。
组合是node-tap
并行运行测试(每个测试,文件一个过程)。因此,您将创建的文件越多,并且测试将更快。 Fastify的inject
功能将避免无聊的Address already in use
错误。
与npm install tap -D
安装后,让我们一起使用简短的tap
示例。
// test/index.test.js
const t = require('tap')
t.test('my first test', async t => {
t.ok(true, 'my first assertion')
})
您可以看到,此框架非常容易且清晰使用:您在必须运行断言的函数中定义了一些.test()
.node-tap
是一个功能完整的测试框架,您会喜欢它的功能。
现在您可以简单地使用:
运行文件
node test/index.test.js
或在package.json
中添加脚本:
{
"scripts": {
"test": "tap test/**.test.js"
}
}
创建可测试的应用程序
在我们的previous article中,我们创建了一个CRUD应用程序。我们将优化它,并使其更可测试。
为了使其可测试,我们需要改进app.js
文件并将配置加载分解。现在,fastify-env
默认情况下从.env
文件加载配置。
运行测试时,我们想从.env.test
加载配置或直接注入。
module.exports = fp(async function application (app, opts) {
await app.register(require('fastify-env'), {
data: opts.envData,
schema: {
// ... old code
我们添加了data
参数。现在,fastify-env
将将schema
检查应用于data
对象。当data
是虚假的时,将使用process.env
对象。通过这种方式,我们可以通过直接注入所需的配置来测试它。
如果存在fastify-env
插件也将加载.env
文件,但不会覆盖data
对象。
仅此而已!现在我们可以写我们的测试用例!
编写测试
测试案例我们的应用程序需求如下:
- 创建一个todo
- 阅读todo
- 更新todo
- 阅读已更新的todo
- 删除todo
- 更新一个不存在的待办事项
- 删除不存在的todo
让我们在test/legacy.test.js
文件中创建第一个测试用例:
const t = require('tap')
const fastify = require('fastify')
const appModule = require('../app')
t.test('create', async t => {
const app = fastify()
app.register(appModule, {
envData: {
NODE_ENV: 'testing',
MONGO_URL: 'mongodb://localhost:27017/my-todo-app'
}
})
t.teardown(() => app.close()) // let's close the server after the test
const response = await app.inject({
method: 'POST',
url: '/todos',
payload: {
text: 'test todo'
}
})
t.equal(response.statusCode, 201)
const todo = response.json()
t.ok(todo.id, 'the id has been returned')
})
现在运行node test/legacy.test.js
将显示此输出:
TAP version 13
# Subtest: create
ok 1 - should be equal
ok 2 - the id has been returned
1..2
ok 1 - create # time=206.184ms
1..1
太好了!我们创建了一个创建todo并返回ID的测试用例。
备忘录:记住在运行测试之前运行
npm run mongo:start
以旋转数据库。
如您所见,inject
方法接受一个输入对象:
-
method
:http方法 -
url
:url -
payload
:发送载荷 -
headers
:发送的标题 -
query
:查询字符串
让我们继续其他测试用例:
// ...previous code..
const todo = response.json()
t.ok(todo.id, 'the id has been returned')
t.test('read', async t => {
const response = await app.inject({
method: 'GET',
url: '/todos'
})
t.equal(response.statusCode, 200)
t.equal(response.json().length, 1)
t.notOk(response.json()[0].done)
})
})
现在,我们正在为create
测试用例创建一个子测验:read
。如您所见,我们正在检查状态代码和响应的长度:我们已经插入了todo,然后我们正在阅读待办事项列表并检查只有一个元素。
如果我们再次运行,我们会遇到错误!
...
diff: |
--- expected
+++ actual
@@ -1,1 +1,1 @@
-1
+2
...
这是由于我们正在使用相同的数据库,并且先前的测试用例已插入了todo,在第二次运行中,我们添加了另一个。
实施集成测试时,这是一个常见的问题。创建集成测试需要一个阶段开始之前:
- 旋转:当我们准备数据库运行测试时。
如前所述,这对于复制生产中发现的问题很有用。在一个旋转阶段,我们可以创建需要复制错误的数据,然后验证在实现之后修复了该错误。
这很有用,因为测试运行后,您也可以在数据库上检查数据!因此,您将立即准备修复错误并在应用程序中本地播放。
让我们更新我们的测试文件:
const mongoClean = require('mongo-clean')
const { MongoClient } = require('mongodb')
t.test('spin up phase - prepare data', async t => {
const c = await MongoClient.connect('mongodb://localhost:27017/my-todo-app')
await mongoClean(c.db())
c.close()
})
t.test('create', async t => {
// ...
现在,运行我们的测试将成功:
# Subtest: create
ok 1 - should be equal
ok 2 - the id has been returned
# Subtest: read
ok 1 - should be equal
ok 2 - should be equal
ok 3 - expect falsey value
1..3
ok 3 - read # time=5.999ms
1..3
ok 1 - create # time=211.436ms
1..1
# time=216.488ms
做得好!我们现在有工作集成测试!
现在,您拥有所有可以构建可测试应用程序的部分,并完成我们之前列出的缺失测试用例。
Insights:如果您创建多个文件来测试您的应用程序,请记住使用不同的数据库名称。您只需要自定义
envData.MONGO_URL
参数。这将避免测试之间的冲突。
如果您想全部看到它们,请给koude35存储库进行检查。
概括
我们在本教程中看到了很多东西。
- 如何将
node-tap
用于我们的测试。 - 如何使用
fastify-env
插件进行可测试的应用程序。 -
fastify.inject
调用应用程序端点的方法。 - 如何处理集成测试。
现在您需要在Fastify中练习并构建自己的应用程序!
评论并分享您是否喜欢这篇文章!