✅
DBがPostgreSQLなHonoアプリをPGliteでテストする
素朴にPostgreSQLに繋いでデータ拾ってくるとこんな感じ?
app.ts
import { Hono } from "hono";
import { drizzle } from "drizzle-orm/node-postgres";
import pg from "pg";
import * as schema from "/path/to/schema";
const pool = new pg.Pool({
connectionString: process.env.DATABASE_URL,
});
const db = drizzle(pool, { schema });
export const app = new Hono().get("/todos", async (c) => {
const rows = await db.query.todos.findMany();
return c.json(rows);
});
schema.ts
import { boolean, pgTable, serial, text } from "drizzle-orm/pg-core";
export const todos = pgTable("todos", {
id: serial("id").primaryKey(),
title: text("title").notNull(),
done: boolean("done").notNull().default(false),
});
まずはappを何かしらの方法で生成出来るようにする
app.ts
import { Hono } from "hono";
import { drizzle } from "drizzle-orm/node-postgres";
+ import type { drizzle as pglite } from "drizzle-orm/pglite";
import pg from "pg";
import * as schema from "/path/to/schema";
const pool = new pg.Pool({
connectionString: process.env.DATABASE_URL,
});
const db = drizzle(pool, { schema });
- const app = new Hono().get("/todos", async (c) => {
- const rows = await db.query.todos.findMany();
-
- return c.json(rows);
- });
+ type DB =
+ | ReturnType<typeof drizzle<typeof schema>>
+ | ReturnType<typeof pglite<typeof schema>>;
+
+ export function createApp(db:DB){
+ return new Hono()
+ .get("/todos",async(c)=>{
+ const rows = await db.query.todos.findMany();
+
+ return c.json(rows);
+ })
+ }
+
+ export const app = createApp(db);
...
テストの準備をする
setup.ts
import { PGlite } from "@electric-sql/pglite";
import { sql } from "drizzle-orm";
import { drizzle } from "drizzle-orm/pglite";
import { migrate } from "drizzle-orm/pglite/migrator";
import { afterAll, afterEach, beforeAll } from "vitest";
import * as schema from "/path/to/schema";
let pglite: PGlite;
export let testDB: ReturnType<typeof drizzle<typeof schema>>;
const migrationsFolder = "drizzle/migrations"
beforeAll(async () => {
pglite = new PGlite();
testDB = drizzle(pglite, { schema });
await migrate(testDB, { migrationsFolder });
await seed();
});
afterEach(async () => { // テストが終わる度にDBを初期化する
await testDB.execute(sql`drop schema if exists public cascade`);
await testDB.execute(sql`create schema public`);
await testDB.execute(sql`drop schema if exists drizzle cascade`);
await testDB.execute(sql`create schema drizzle`);
await migrate(testDB!, { migrationsFolder });
await seed();
});
afterAll(async () => {
if (pglite) {
await pglite.close();
}
});
async function seed() { // 初期データ
await testDB.insert(schema.todos).values([
{
id: 1,
title: "test1",
done: false,
},
{
id: 2,
title: "test2",
done: true,
},
]);
}
取得のテストを書く
app.test.ts
import { testClient } from "hono/testing";
import { test, expect } from "vitest";
import { testDB } from "/path/to/setup";
import { createApp } from "/path/to/index";
test("GET tasks", async () => {
const app = createApp(testDB);
const client = testClient(app);
const res = await client.todos.$get();
const json = await res.json();
expect(res.json.length).toEqual(2);
...
});
後はテスト実行
$ npx vitest run
速い!
Discussion