こちらは、現時点で最新のAdonisJS v5の記事になります。
テストの導入手順とAdonis v4との変更点を紹介します。
公式ドキュメント
https://docs.adonisjs.com/guides/testing/introduction
テストはVowという内製?のテストツールからJapaに変更されています。
全体的に大きな変更はなく、メソッド名が違ったりの小さな変化でした。
Test機能を追加する
$ node ace configure tests
[ wait ] installing @japa/runner, @japa/preset-adonis ..
なぜかインストールが進まないので、一旦停止してpackageを追加します。
$ yarn add -D @japa/runner @japa/preset-adonis
$ node ace configure tests
TestDB設定
test用のDBを用意する。
テスト環境でのみ読み込まれる環境変数.env.testを作成します。
DB_DATABASE=adonis-test
テスト実行前にDBのマイグレーションを実行する設定を追加
export const runnerHooks: Required<Pick<Config, 'setup' | 'teardown'>> = {
setup: [
() => TestUtils.ace().loadCommands(),
+ () => TestUtils.db().migrate(),
],
teardown: [],
}
Drive設定の追加
自分のサービスではAdonisで画像ファイルを作成する機能があるため、テストで作成されたファイルはテスト終了後に削除する設定が必要。
テストで作成されたファイルを削除する。
export const runnerHooks: Required<Pick<Config, 'setup' | 'teardown'>> = {
teardown: [
async () => {
const list = await Drive.list('./').recursive().toArray()
await Promise.all(await list.map((item) => Drive.delete(item.location)))
}
],
}
このままだと全環境のファイルを削除してしまうので、テスト環境でのファイルの保存先を変更する。
export default driveConfig({
disks: {
local: {
root: Env.get('NODE_ENV') === 'test' ? Application.tmpPath('upload') : Application.publicPath('upload'),
}
}
})
Testの書き方
テストを追加する
$ node ace make:test functional user
CREATE: tests/functional/user.spec.ts
作成されたファイルにテスト内容を書いていく。
テストの書き方はJapaなので公式サイトを参考に書いてください。
https://japa.dev/docs
Factoryを作成する
モデルのモックデータとなるFactoryを作成する
$ node ace make:factory user
CREATE: database/factories/UserFactory.ts
import user from 'App/Models/user'
import Factory from '@ioc:Adonis/Lucid/Factory'
export default Factory.define(user, ({ faker }) => {
return {
email: faker.internet.email(),
password: faker.internet.password(),
}
}).build()
Adonis v4との違い
テストツールをAdonis v4ではassertにchaiを使っていたが、Adonis v5からjapaというものに変わり、書き方が変わっているので変更点だけ紹介する。
全体的な書き方の違い
Adonis v4
const { test } = use('Test/Suite')('User')
const Factory = use('Factory')
const Mail = use('Mail')
const UserFactory = Factory.model('App/Models/User')
test('can create user if valid data', async ({ assert }) => {
// some tests
})
Adonis v5
import { test } from '@japa/runner'
import Mail from '@ioc:Adonis/Addons/Mail'
import UserFactory from 'Database/factories/UserFactory'
// test関数の似た感じ
test.group('User', () => {
test('can create user if valid data', async ({ assert, client }) => {
// some tests
})
})
Database Transaction
テスト間でデータが影響しないように、テスト毎にトランザクションを貼り、終了後にロールバックします。
Adonis v4
const { test, trait } = use('Test/Suite')('User registration')
trait('DatabaseTransactions')
Adonis v5
import Database from '@ioc:Adonis/Lucid/Database'
test.group('Group name', (group) => {
group.each.setup(async () => {
await Database.beginGlobalTransaction()
return () => Database.rollbackGlobalTransaction()
})
})
ApiClient
Adonis v4
const response = await client.post('/api/v1/user').send(data).end()
Adonis v5
const response = await client.post('/api/v1/user').fields(data)
Response Assert
ApiClientのレスポンスのアサーション
Adonis v4
response.assertJSONSubset([
{
message: '会員登録完了しました',
},
])
Adonis v5
response.assertBodyContains({
message: '会員登録完了しました',
})
// error response
response.assertBodyContains({
errors: [{
message: 'メールアドレスが正しくありません',
field: 'email',
rule: 'email',
}]
})
メール
Adonis v4
test('hoge', async ({}) => {
Mail.fake()
const recentEmail = Mail.pullRecent()
assert.equal(recentEmail.message.to[0].address, email)
assert.equal(recentEmail.message.subject, '会員登録いただきありがとうございます。')
Mail.restore()
})
Adonis v5
test('hoge', async ({}) => {
const mailer = Mail.fake()
mailer.exists((mail) => {
const sameAddress = mail.to?.some(to => to.address == email) || false
const sameSubject = mail.subject === '会員登録いただきありがとうございます。'
return sameAddress && sameSubject
})
Mail.restore()
})
Factory
Adonis v4
const user = await UserFactory.create({
password: 'password',
})
Adonis v5
const user = await UserFactory.merge({
password: 'password',
}).create()
この他にも、AdonisJS v5へのアップグレードで行ったことをまとめました。
なにか役に立てたら幸いです。