🕌

【Prisma】APIテスト実装方法

2023/04/04に公開

はじめに

開発において、APIのテスト作成を担当することになったので、備忘録として残しておきます。

目次

1.Prismaの単体テストとは

2.Prisma mockとは

3.「Singleton」でのテスト実装方法

1.Prismaの単体テストとは

Prismaは、TypeScriptやJavaScriptなどのプログラミング言語で記述されたデータベースアクセスライブラリ

単体テストを実行することで、データベースとのインタラクションが期待どおりに動作するかを確認することができる。

Prismaの単体テストは、通常、以下のような手順で実行されます。

1.テスト用のデータベースをセットアップする。

2.テストスクリプトを実行する。

3.テストスクリプトは、Prismaを使用してデータベースにアクセスし、期待される動作を実行する。
4.テスト結果を検証し、問題があれば修正する。

具体的には、Prismaの単体テストでは、以下のようなテストケースを実行することが一般的です。
・データを作成、読み取り、更新、削除する操作が期待どおりに機能するかを確認する。
・バリデーションやエラーハンドリングが期待どおりに機能するかを確認する。
・クエリパフォーマンスが十分であることを確認する。
これらのテストは、Prismaがデータベースとの間で期待通りのインタラクションを行うことを保証し、信頼性の高いアプリケーションを開発するために不可欠です。

Prismaの単体テストでは、singleton instanceとdependency injectionの二つの実装方法があります。今回は、Singletonで実装したので、Singletonの実装方法について説明します。

2.Prisma mockとは

Prismaで単体テストを作成するうえで外せない考え方として、Mockがあります。

Mockとは、テストのために、本物のデータベースにアクセスする代わりに、テスト用のデータを提供する方法。

イメージ図を書いてみました。

メリット:

1.テスト中に実際のデータベースを変更することなく、テストを繰り返し実行することができる。
2.開発者はテストデータを簡単に作成し、Prismaの各メソッドが期待どおりに動作するかどうかを確認できる。

例:データを追加するためのメソッドをテストする場合
1.Mockを使用してテストデータを作成する
2.PrismaのSingletonを使用してPrisma Clientを初期化する
3.Prismaのクエリメソッドを使用して、テストデータをデータベースに追加し、結果を確認する


おさらいすると、Mockは、テスト中にPrismaが使用するデータベースの代わりに使用されるデータのことであり、テストを繰り返し実行し、アプリケーションの機能を確認するために使用するものでした。
次に、「Singleton」でのテスト実装方法について説明したいと思います。

3.「Singleton」でのテスト実装方法

1.jest-mock-extendedパッケージをインストールします。

npm install jest-mock-extended@2.0.4 --save-dev

2.プロジェクトのrootにclient.tsという名前のファイルを作成し、次のコードを追加します。これにより、Prisma clientがインスタンス化されます。

import { PrismaClient } from '@prisma/client'

const prisma = new PrismaClient()
export default prisma

3.次に、プロジェクトのrootにsingleton.tsという名前のファイルを作成し、以下を追加します。

import { PrismaClient } from '@prisma/client'
import { mockDeep, mockReset, DeepMockProxy } from 'jest-mock-extended'

import prisma from './client'

jest.mock('./client', () => ({
  __esModule: true,
  default: mockDeep<PrismaClient>(),
}))

beforeEach(() => {
  mockReset(prismaMock)
})

export const prismaMock = prisma as unknown as DeepMockProxy<PrismaClient>

これでMockを使える環境になりました。
参考文献→Unit testting with Prisma

backendにroutesとmodelsフォルダを作成します。
routesはアプリの表層、つまり200,402,404エラーが出るか確認するためのコード。
modelsはデータ層、つまりほしいデータが返ってきているか確認するためのコード。

1.まずはmodelsのテストから

まずはmodelsにて欲しいデータが返ってくるかどうかの確認をします。
ここでは、欲しいデータ(test_id,test_name)が取得できているか調べるコードです。

import { Decimal } from "@prisma/client/runtime";
import { ErrorCode } from "../api/ErrorResponse";
import { CoretechMapData } from "../types/coretechmapdata";
import prisma from "./client";

/**
 * コア技術一覧を取得
 * data = {
 *   test_id,
 *   test_name
 * }[];
 */
export async function findTestData() {
    return prisma.testdata.findMany({
        select: {
            test_id: true,
            test_name: true
        }
    }).then((data) => {
        if (data.length !== 0) {
            return data;
        } else {
            throw ErrorCode.NotFoundTarget;
        }
    }).catch((e) => {
        console.log(e)
        throw ErrorCode.UnexpectedError
    }).finally(async () => await prisma.$disconnect())
}

2.次にroutesのテスト

ここではmodelsのtest_pagesに作成したfindTestDataという関数が欲しいデータを取ってきて、正しく画面が表示されているか(200,401,404)調べるテストコードです。

import express, { Request, Response } from 'express';
import bodyParser from 'body-parser';
import { ErrorCode, ErrorResponse } from '../api/ErrorResponse';
import { findTestData } from '../models/test_pages';

const router = express.Router();

router.use(bodyParser.json());

router.get('/', async (req: Request, res: Response) => {
    var data
    try {
        data = await findTestData();
    } catch (e) {
        switch (e) {
            case ErrorCode.NotFoundTarget:
                return res.status(404).json(ErrorResponse(ErrorCode.NotFoundTarget));
            case ErrorCode.UnexpectedError:
                return res.status(401).json(ErrorResponse(ErrorCode.UnexpectedError));
        }
    }
    res.status(200).json(data);
});
export default router;

これにてテストコードの作成は完了です。

最後に

Prismaの単体テストについて理解できたでしょうか。
PrismaのMockの考え方は重要なので今後の業務でも活かしていけたらいいですね♪

Discussion