Open2
Bun.js をバックエンドで使いたい
Bun 公式の Docker イメージ oven/bun
上では Prisma が使えないので要注意。Node.js の公式イメージにさらに Bun をインストールして作ったコンテナ内では問題なく使えるのでどうやら Node.js も必要ぽい
FROM node:20.10.0
RUN curl -fsSL https://bun.sh/install | bash
jest-prisma を bun test でもなんとか使えるようにする試み。
x
テーブルにメッセージを投稿するための post
関数がありこの関数をテストしたい。
schema.prisma
model X {
id Int @id @default(autoincrement())
message String
createdAt DateTime @default(now())
}
x.ts
import type { PrismaClient } from "@prisma/client";
// prismaClient を引数で受け取ることでテストしやすくしている
export const post = async (params: { prisma: PrismaClient; message: string }) => {
const { message, prisma } = params;
return await prisma.x.create({ data: { message } });
};
jest-prisma を使わずに書くと以下のようなテストになる。このテストは実行する度に x
テーブルのレコード数が増えていくので2回目以降は失敗してしまう。
x.test.ts
import { PrismaClient } from '@prisma/client';
import { expect, test } from "bun:test";
import { post } from "./x";
test("post", async () => {
const prisma = new PrismaClient();
const res = await post({ message: "first post", prisma });
expect(res.message).toBe("first post");
const timeline = await prisma.x.findMany();
expect(timeline.length).toBe(1);
});
ここで jest-prisma を 使ってテスト終了時に db を元の状態に戻したくなる。しかし jest-prisma は Jest の testEnvironment
を使っているのでそのままでは bun test には組み込めない。
そこで以下のような preloader を書いて無理やり組み込む。
preload.ts
import type { EnvironmentContext, JestEnvironmentConfig } from "@jest/environment";
import type { Circus } from "@jest/types";
import type { PrismaClient } from "@prisma/client";
import { JestPrisma, PrismaEnvironmentDelegate } from "@quramy/jest-prisma-core";
import { afterEach, beforeEach } from "bun:test";
declare global {
// eslint-disable-next-line no-var
var bunTestPrisma: JestPrisma<PrismaClient>;
}
const delegate = new PrismaEnvironmentDelegate(
{
projectConfig: { testEnvironmentOptions: {} },
globalConfig: { rootDir: "" }
} as JestEnvironmentConfig,
{ testPath: "" } as EnvironmentContext,
);
global.bunTestPrisma = await delegate.preSetup();
beforeEach(async () => {
await delegate.handleTestEvent({ name: "test_start" } as Circus.Event);
});
afterEach(async () => {
await delegate.handleTestEvent({ name: "test_done" } as Circus.Event);
});
bunfig.toml
[test]
preload = "./preload.ts"
この preloader で global 空間に bunTestPrisma が生成されるので、x.test.ts
で PrismaClient
を生で使っていた箇所を bunTestPrisma.client
に置き換える。
x.test.ts
- const prisma = new PrismaClient();
+ const prisma = bunTestPrisma.client;
これで何度実行しても成功するテストになった😃
autoincrement
している id は元に戻らず進み続けるので注意 → DBの自動連番がロールバックしても戻らない理由