SQLite3+Preisma 환경에서 Vitest로 Unit Test 쓰기
스택
yarn prisma studio
에서 DB를 확인할 수 있다는 것은 정말 드문 일이다.초기 설정
TypeScript 스크립트를 실행할 수 있는 환경을 만듭니다.실행 중에는
ts-node
대신 esbuild-register
를 사용하여 더욱 빨리 실행할 수 있다.우선 테스트를 포함하지 않고 강좌 단계를 간단하게 실현한다.
$ mkdir prisma-sqlite3
$ cd prisma-sqlite3
$ yarn init -y
$ yarn add -D prisma typescript esbuild esbuild-register @types/node
$ touch index.ts
package.json
의scripts
는 다음과 같다.package.json
"scripts": {
"start": "node -r esbuild-register index.ts",
},
tsconfig.json
도 설정했다.교과서와 같다.tsconfig.json
{
"compilerOptions": {
"sourceMap": true,
"outDir": "dist",
"strict": true,
"lib": ["esnext"],
"esModuleInterop": true
}
}
prisma의 초기 설정 명령을 실행합니다.prisma
디렉터리를 만들고 설정 파일을 부하에 설정합니다.$ yarn prisma init
생성된 설정 파일을 SQLite3으로 덮어씁니다.SQLite3의 데이터 파일에 대한 경로가 정의되었으나 실제로 작성할 필요는 없습니다..env
DATABASE_URL="file:./dev.db"
prisma/schema.prismagenerator client {
provider = "prisma-client-js"
}
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}
model Post {
id Int @id @default(autoincrement())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// SQLite では @db.VarChar(255) はサポートされていないので外す
title String
content String?
published Boolean @default(false)
author User @relation(fields: [authorId], references: [id])
authorId Int
}
model Profile {
id Int @id @default(autoincrement())
bio String?
user User @relation(fields: [userId], references: [id])
userId Int @unique
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
profile Profile?
}
scheme의 정의가 완료되면 다음 절차를 수행하여 DB에서 표를 작성합니다.$ yarn prisma migrate dev --name init
yarn prisma studio
를 실행할 때 브라우저에서 만든 테이블을 확인할 수 있습니다.실행 확인
스크립트를 기술하기 위해 데이터를 처리하는 Proisma 클라이언트 라이브러리를 추가합니다.
$ yarn add @prisma/client
index.tsimport { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
async function main() {
await prisma.user.create({
data: {
name: "Alice",
email: "[email protected]",
posts: {
create: { title: "Hello World" },
},
profile: {
create: { bio: "I like turtles" },
},
},
});
const allUsers = await prisma.user.findMany({
include: {
posts: true,
profile: true,
},
});
console.dir(allUsers, { depth: null });
}
main()
.catch((e) => {
throw e;
})
.finally(async () => {
await prisma.$disconnect();
});
일단 실행해 보자.yarn start
에서 데이터 투입 결과를 나타낼 수 있다.시험을 쓰다
다음은 본론.DB의 unit test를 정의합니다.덮어쓰기
c8
도 가져왔기 때문에 가져옵니다.$ yarn add -D vitest c8
$ touch index.test.ts
테스트를 쓰기 전에package.json
테스트 실행에 사용할 스크립트를 미리 기술합니다.이번에는 실제 DB에 투입되기 때문에 테스트 수행 전 리셋 테이블prisma migrate reset -f
을 실행한다.package.json
"scripts": {
"start": "node -r esbuild-register index.ts",
"test": "vitest run",
"coverage": "vitest run --coverage",
"db:reset": "prisma migrate reset -f",
"db:test": "yarn db:reset && yarn test",
"db:test:coverage": "yarn db:reset && yarn coverage"
},
index.test.ts
쓰기 테스트.이럴 때는 잠시 우직해도 되기 때문에 먼저 통과한다.이후 함수화 등을 진행한다.index.test.ts
import { test, expect } from "vitest";
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
test("User does not exist in the initial DB", async () => {
const users = await prisma.user.findMany({
include: {
posts: true,
profile: true,
},
});
expect(users).toEqual([]);
});
테스트를 기술하고 실행하다.실패할 때 표의 상태를 확인합니다.$ yarn db:test
성공하면 함수로 잘라냅니다.index.test.ts
export async function findAllUser() {
const users = await prisma.user.findMany({
include: {
posts: true,
profile: true,
},
});
return users;
}
test("User does not exist in the initial DB", async () => {
const users = await findAllUser();
expect(users).toEqual([]);
});
최종적으로 index.ts
로 이동하여 읽습니다.그리고 이것을 반복해서 테스트 모드를 추가합니다.index.test.ts
import { findAllUser } from "./index";
test("User does not exist in the initial DB", async () => {
const users = await findAllUser();
expect(users).toEqual([]);
});
테스트 용례 증가
index.ts
에서 기본 CRUD 모드를 구현합니다.다음에 deleteUserById()
가 실패합니다.index.ts
import { PrismaClient, Prisma } from "@prisma/client";
const prisma = new PrismaClient();
export async function createUser(user: Prisma.UserCreateInput) {
await prisma.user.create({ data: user });
}
export async function findAllUser() {
const user = await prisma.user.findMany({
include: {
posts: true,
profile: true,
},
});
return user;
}
export async function findUserById(id: number) {
const user = await prisma.user.findFirst({
where: { id },
include: {
posts: true,
profile: true,
},
});
return user;
}
export async function updateUserById(id: number, user: Prisma.UserUpdateInput) {
await prisma.user.update({
where: { id },
data: user,
});
}
export async function deleteUserById(id: number) {
await prisma.user.delete({ where: { id } });
}
export async function disconnectDB() {
await prisma.$disconnect();
}
테스트도 index.test.ts
에 쓰십시오.index.test.ts
import { describe, expect, test, afterAll } from "vitest";
import { Prisma } from "@prisma/client";
import {
createUser,
deleteUserById,
disconnectDB,
findAllUser,
findUserById,
updateUserById,
} from "./index";
const demoUser: Prisma.UserCreateInput = {
name: "Alice",
email: "[email protected]",
posts: {
create: { title: "Hello World" },
},
profile: {
create: { bio: "I like turtles" },
},
};
afterAll(async () => {
await disconnectDB();
});
test("User does not exist in the initial DB", async () => {
const users = await findAllUser();
expect(users).toEqual([]);
});
describe("CRUD user", async () => {
test("create user", async () => {
await createUser(demoUser);
const user = await findUserById(1);
expect(user?.name).toBe("Alice");
expect(user?.email).toBe("[email protected]");
expect(user?.posts[0].title).toBe("Hello World");
expect(user?.posts[0].published).toBe(false);
expect(user?.profile?.bio).toBe("I like turtles");
});
test("update user", async () => {
await updateUserById(1, {
name: "Emma",
email: "[email protected]",
});
const user = await findUserById(1);
expect(user?.name).toBe("Emma");
expect(user?.email).toBe("[email protected]");
});
test("delete user", async () => {
await deleteUserById(1);
const user = await findUserById(1);
expect(user).toBe(null);
});
});
yarn db:test
에서 실행됩니다.delete user
테스트에 실패했습니다.조사 결과 외부 버튼 제한이 실패한 것으로 밝혀졌다.수정 방침은 여러 가지지만 스쉘을 재고하기로 했다.
prisma/schema.prisma
model Post {
- author User @relation(fields: [authorId], references: [id])
+ author User @relation(fields: [authorId], references: [id], onDelete: Cascade, onUpdate: Cascade)
}
model Profile {
- user User @relation(fields: [userId], references: [id])
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade, onUpdate: Cascade)
}
업데이트된 Scheme을 DB에 반영합니다.prisma/migrations/
부하에서 DB 업데이트용 SQL을 생성한 것을 확인할 수 있습니다.$ yarn prisma migrate dev --name update
DB의 업데이트yarn db:test
를 반영하여 테스트를 실시하면delete user
테스트도 성공했기 때문이다.총결산
나는 유닛 테스트를 직접 쓴 경험이 거의 없기 때문에 이렇게 쓰는 것이 맞는지 모르겠다. 어쨌든 해냈다.
Preisma Celient 측에서 DROP 테이블의 API를 찾을 수 없기 때문에 테스트 실행 전에 실행
prisma migrate reset
했습니다. 이보다 더 좋은 방법이 있으면 알려주세요.
Reference
이 문제에 관하여(SQLite3+Preisma 환경에서 Vitest로 Unit Test 쓰기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/mr_ozin/articles/6cc81db8a8d221텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)