数据库断言
本指南涵盖在 AdonisJS 测试中断言数据库状态。你将学习如何:
- 配置数据库断言插件
- 断言表中的行存在或缺失
- 检查行数以及空表
- 验证模型实例存在或已被删除
概述
在测试修改数据库的功能时,你经常需要验证最终的状态:行被创建了吗?它被删除了吗?记录的数量是否恰好正确?Lucid 提供了一个 Japa 插件,将数据库断言方法直接添加到测试上下文中,这样你就可以在不编写原始查询的情况下验证数据库状态。
该插件在测试上下文上暴露了一个 db 对象,其方法包括 assertHas、assertMissing、assertCount,以及模型级别的断言。每个方法都会查询数据库,并在断言失败时抛出带有清晰消息的 AssertionError。
设置
在你的 tests/bootstrap.ts 文件中注册 dbAssertions 插件。
tests/bootstrap.ts
import app from '@adonisjs/core/services/app'
import { dbAssertions } from '@adonisjs/lucid/plugins/db'
export const plugins: Config['plugins'] = [
assert(),
pluginAdonisJS(app),
apiClient(),
dbAssertions(app),
]
注册后,db 属性即可在测试上下文中使用。你可以通过解构测试回调参数来访问它。
tests/functional/users.spec.ts
import { test } from '@japa/runner'
test('creates a user', async ({ db }) => {
// 使用 db.assertHas、db.assertMissing 等。
})
断言行存在
assertHas 方法检查表中是否至少有一行与给定的数据匹配。传入一个表名和一个用于匹配的对象(由列/值对组成)。
tests/functional/users.spec.ts
import { test } from '@japa/runner'
import testUtils from '@adonisjs/core/services/test_utils'
test.group('Users', (group) => {
group.each.setup(() => testUtils.db().truncate())
test('registers a new user', async ({ client, db }) => {
await client.post('/register').json({
email: '[email protected]',
password: 'secret123',
})
// 当至少有一行匹配时通过
await db.assertHas('users', { email: '[email protected]' })
})
})
你可以传入可选的第三个参数,以断言匹配行的确切数量。
tests/functional/users.spec.ts
test('promotes multiple users to admin', async ({ client, db }) => {
await User.createMany([
{ email: '[email protected]', password: 's', role: 'user' },
{ email: '[email protected]', password: 's', role: 'user' },
])
await client.post('/admin/promote-all')
// 仅当恰好有 2 行匹配时通过
await db.assertHas('users', { role: 'admin' }, 2)
})
断言行缺失
assertMissing 方法是 assertHas 的逆操作。它验证表中没有任何行与给定的数据匹配。
tests/functional/users.spec.ts
test('deletes inactive users', async ({ client, db }) => {
await User.create({ email: '[email protected]', password: 's', active: false })
await client.post('/admin/cleanup')
await db.assertMissing('users', { active: false })
})
断言行数
assertCount 方法检查表中的总行数,而不管其内容如何。
tests/functional/users.spec.ts
test('seeds default users', async ({ client, db }) => {
await client.post('/setup/seed')
await db.assertCount('users', 5)
})
assertEmpty 方法是 assertCount(table, 0) 的简写形式。它验证一个表完全没有行。
tests/functional/tokens.spec.ts
test('clears all expired tokens', async ({ client, db }) => {
await client.post('/admin/clear-tokens')
await db.assertEmpty('auth_access_tokens')
})
断言模型存在
在使用 Lucid 模型时,你可以直接对模型实例进行断言,而不必编写表级别的查询。assertModelExists 方法检查模型的 primary key 是否仍然存在于数据库中。
tests/functional/users.spec.ts
import User from '#models/user'
test('creates a user record', async ({ client, db }) => {
await client.post('/register').json({
email: '[email protected]',
password: 'secret123',
})
const user = await User.findByOrFail('email', '[email protected]')
await db.assertModelExists(user)
})
assertModelMissing 方法验证模型实例不再存在于数据库中。这对于测试删除操作很有用。
tests/functional/users.spec.ts
test('deletes a user', async ({ client, db }) => {
const user = await User.create({
email: '[email protected]',
password: 'secret123',
})
await client.delete(`/users/${user.id}`)
await db.assertModelMissing(user)
})
断言参考
| Method | Description |
|---|---|
assertHas(table, data, count?) | 验证与 data 匹配的行存在。当提供 count 时,检查匹配的精确数量。 |
assertMissing(table, data) | 验证没有行与 data 匹配。 |
assertCount(table, count) | 验证表恰好拥有 count 总行数。 |
assertEmpty(table) | 验证表没有行。assertCount(table, 0) 的简写形式。 |
assertModelExists(model) | 通过 primary key 验证模型实例存在于数据库中。 |
assertModelMissing(model) | 验证模型实例不存在于数据库中。 |