プログラミング

JestでNode.js、ExpressとMongooseを使ったアプリのテストを書く

JestでNode.js、ExpressとMongooseを使ったアプリのテストを書く

Jest で Express と Mongoose をまとめてテストするやつでちょっと探すの苦労したのでまとめてメモ書き。

なんかいろいろググった結果この記事を一番参考にした。

とりあえず必要な開発用パッケージをインストールします。 npm i -D mongodb-memory-server

mongodbの代わりにmongodb-memory-serverが動くようにするためにテスト用に db ファイルを作成します。

/___tests__/config/database.ts

import mongoose from "mongoose";
import { MongoMemoryServer } from "mongodb-memory-server";
import { MongoClient } from "mongodb";

let connection: MongoClient;
let mongoServer: MongoMemoryServer;

const connect = async () => {
  mongoServer = await MongoMemoryServer.create();
  connection = await MongoClient.connect(mongoServer.getUri(), {});
};

const close = async () => {
  await mongoose.connection.dropDatabase();
  await mongoose.connection.close();
  await mongoServer.stop();
};

const clear = async () => {
  const collections = mongoose.connection.collections;
  for (const key in collections) {
    await collections[key].deleteMany({});
  }
};
export default { connect, close, clear };

実際はあえて途中でclearしないことでそのまま他のメソッドのリクエストも続けて書いたりしました。 本当はそれぞれ分けて書いたほうがいいんだろうけど。

/___tests__/tags.test.ts

import request from "supertest";
import app from "../src/index";
import db from "./config/database";

const agent = request.agent(app);

beforeAll(async () => await db.connect());
afterEach(async () => await db.clear());
afterAll(async () => await db.close());

describe("tags", () => {
  let tag = { name: "test-tag", id: undefined };

  describe("POST /tags", () => {
    test("successful", async () => {
      const res = await agent.post("/tags").send(tag);
      expect(res.statusCode).toEqual(201);
      tag.id = res.body.id;
      expect(res.body).toEqual(expect.objectContaining(tag));
    });
  });
});

ちなみにポートが戦ってしまったので、テストのときはアプリを立ち上げないようにした。

package.json

"scripts": {
  "test": "export NODE_ENV=test && jest --forceExit --runInBand",
},

/src/index.ts

if (process.env.NODE_ENV !== "test") {
  app.listen(port, () => {
    console.log(`Express app listening at ${process.env.BASE_URI}:${port}`);
  });
}

全体的に割と読めばわかるというか、大したことはしていないけど正直いろんなドキュメント見て回らないと書けないなあと思ったのでメモ。 多分コピペすれば動くと思う。