NESTJSとMongoDBによる統合テストセットアップ



私のブログに投稿されたhttps://blog.merckx.fr/integration-testing-setup-with-nestjs-and-mongodb/
自動化されたテストは、ソフトウェアを作成するときに膨大な値を提供します.テスト駆動の開発アプローチに従うことができます:あなたのテストを書くことができますし、APIとその要件を前に設計し、テストを渡すためにコードを記述します.
よくある質問があります.
  • 私は、単位テスト、統合テストまたはE 2 Eテストを作成しますか?
  • 何をすべきか
  • 私は何をテストしていますか?
  • 多くの議論がまだ続いている間、どれが続くかについてのかなり明確な規則があります:
  • E 2 Eテストは、我々はリリースすることができます質問に非常に良い答えを提供する?しかし、テストが失敗する理由は非常に貧しいものですか?彼らは書くのが高い.
  • 単体テストは正反対です.彼らは失敗の起源を見つけるのが非常に良いです、しかし、彼らがすべて通るならば、あなたが実はリリースすることができるかどうかわかっていて悪いです.彼らは書くのが楽だ.
  • 統合テストは、2つの間の良いバランスを提供します.それらはコンポーネントの統合ポイントをテストしています、そして、あなたは1つのリリースからもう一方まで、あなたの構成要素の間のインタフェースが変わらないならば、あなたの統合テストが通過すると、リリースは展開されることができると仮定することができます.彼らは書くのが安い.単体テストほど安いが、E 2 Eテストよりずっと安い.
  • これは私が統合テストに集中することをお勧めです.統合テストを書くとき、あなたは常に彼らが書くのが簡単でなければならないと心に留めておくべきです.モンクキング機能性はコードを書く必要があるので、避けるべきです.実際にテストに実行するコードからできるだけ多くの統合を目指してください.
    私はNESTJSを使用してプロジェクトの90 %を使用します.それらのプロジェクトの90 %で、私はMongoDBをデータベースとして使います.モジュールのための統合テストを書くテストは、テストされたモジュールの周りのすべての機能性を模擬することなく、単位テストを書くのと同じくらい簡単でなければなりません.したがって、我々は統合テストを実行するときに実際のMongoデータベースを統合する方法を見つける必要があります.これは次の行で提示されることです.

    自分を好意的にし、フレンドリーな開発環境を作る
    Dockerを使って開発環境を設定します.あなたはDockerと友人でないかもしれません、しかし、あなたはよりよくなります.Dockerは以下を有効にする友人です.
  • 一度設定すると、オフラインで作業することができます.クラウド内の開発データベースをホストする必要はありません.
  • あなたは後で生産で使用できるコンテナで動作します
  • あなたのニーズに合わせて多くのワークフローを作成することができます
  • だからあなたのマシンにDockerをインストールしてインストールしてください.それをするには5分必要だhttps://docs.docker.com/get-docker/ そして、あなたは戻って来ることができます.

    アプリケーションをコンテナ化する
    この時点で、あなたのマシン上でDockerを実行し、データベースとしてMongoを使用してNESTJSプロジェクトがあります.私たちは使用するつもりですDocker Compose 異なるサービスを実行するいくつかのコンテナを作成します.下記docker-compose.yml file 2つのサービスを持つ環境を記述します.api and mongo . mongo MongoDBサーバを実行するコンテナを作成しますapi ポートを公開するNodeJS 14を実行するコンテナです3333 and 9229 . この方法では、ネストアプリケーションとデバッガに到達できます.
    version: "3.9"
    services:
      api:
        image: node:14
        volumes:
          - .:/app
        ports:
          - 3333:3333
          - 9229:9229
        depends_on:
          - mongo
        environment:
          NODE_ENV: development
      mongo:
        image: mongo:4.4.8
        volumes:
          - ./.docker/mongodb/data/db/:/data/db/
          - ./.docker/mongodb/data/log/:/var/log/mongodb/
    
    
    あなたはほとんど完全に設定されます.いくつかの役に立つワークフローを説明しましょう.

    必要なものを起動します
    コンテナを設定しました.それは私たちのNESTJSアプリケーションを起動し、テストする時間です.次のコマンドを保存しますpackage.json または、あなたの倉庫のシェルスクリプトとして:
    docker-compose run --service-ports -w /app api bash
    
    これでサービスが開始されますapi and mongo とbashシェルを起動します.このシェルでは、NPMとノードを使用すると、あなたがDockerなしでそれをするのと同じ方法です!通常のコマンドを試してくださいnpm install and npm start and npm test私は通常、私のこのコマンドを保存しますpackage.json の下にstart:env スクリプト
    {
      ...
      "scripts": {
        "start:env": "docker-compose run -w /app api bash",
        ...
      }
    }
    

    テストを一度実行する
    CIでテストを実行する場合は、次のコマンドを使用します.
    docker-compose run -w /app api npm run test
    
    
    ここでtest スクリプトはインスタンスです:
    npm install && jest
    

    書き込み積分テスト
    あなたがNestjsアプリケーションを持っていると想像してくださいPostModule それはコントローラを持っているPostController これには2つのAPIエンドポイントがあります.
  • GET /post : データベースに格納されているすべてのポストを返す
  • POST /post : 新しいポストを作成し、データベースに格納します
  • このモジュールにもサービスがありますPostService あれPostController インスタンスを使用します.サービスはデータベースにアクセスします.モジュールをテストするには、PostServicePostController . コントローラは直接データベースにアクセスしませんし、それを行うためのサービスが必要です.コントローラのテストを書くときは、次の選択肢があります.
  • あなたは完全にサービスを模擬することができます
  • データベースアクセスをモックアップできます
  • モジュール全体の実際の実装を使用することができます.したがって、そのコンポーネントの統合をテストできます
  • 解決策3に向かっています.各統合テストのために、我々は完全に新しいデータベースを作成し、それが完了したら削除します.以下のspecファイルを見てください.
    import { getConnectionToken, MongooseModule } from '@nestjs/mongoose';
    import { NestExpressApplication } from '@nestjs/platform-express';
    import { Test } from '@nestjs/testing';
    import { Connection } from 'mongoose';
    import * as supertest from 'supertest';
    import { IPost } from '../model/post';
    import { PostModule } from '../post.module';
    
    describe('PostController', () => {
      let app: NestExpressApplication;
    
      const apiClient = () => {
        return supertest(app.getHttpServer());
      };
    
      beforeEach(async () => {
        const moduleRef = await Test.createTestingModule({
          imports: [
            MongooseModule.forRoot('mongodb://mongo:27017', { dbName: 'test' }), // we use Mongoose here, but you can also use TypeORM
            PostModule,
          ],
        }).compile();
    
        app = moduleRef.createNestApplication<NestExpressApplication>();
        await app.listen(3333);
      });
    
      afterEach(async () => {
        await (app.get(getConnectionToken()) as Connection).db.dropDatabase();
        await app.close();
      });
    
      it('creates a post', async () => {
        await apiClient()
          .post('/post')
          .send({
            content:
              'I am all setup with Nestjs and Mongo for more integration testing. TDD rocks!',
          })
          .expect(201);
        const posts: IPost[] = (await apiClient().get('/post')).body;
        expect(posts[0].content).toBe(
          'I am all setup with Nestjs and Mongo for more integration testing. TDD rocks!',
        );
        expect(posts[0].likes.length).toBe(0);
      });
    });
    
    
    いくつかのメモ
  • 我々は何もモック
  • 全体をテストするPostModule
  • beforeEach and afterEach 我々のフックは、データベースを作成して、削除します.使用するデータベース名をマングースに指定し、データベースを削除します(app.get(getConnectionToken()) as Connection).db.dropDatabase()
  • 使用するsupertest APIの消費者を作成するには
  • モジュールを追加するだけですPostModule アプリに
  • アプリケーション全体を起動すると、実際のエンドツーエンドテストに非常に近いでしょう
  • 私は、あなたがたった今設定されていると信じています.あなたの処分をすることができます多くの統合テストとして書くことができる環境です.これで、TDDのアプローチを採用し、完全にテストAPIを展開することができます.
    注:で説明したセットアップの例を見つけることができますhttps://github.com/kevinmerckx/nesjts-with-mongo .
    km
    写真でGlen Carrie on Unsplash

    資源
  • An example to setup your repository
  • TDD
  • End-to-End Testing vs Integration Testing
  • Unit vs Integration vs System vs E2E Testing
  • Unit, Integration and End-To-End Tests - Finding the Right Balance
  • The different types of software testing