ホームページ > ウェブフロントエンド > jsチュートリアル > NestJS アプリケーションの単体テストと Etest を作成する方法

NestJS アプリケーションの単体テストと Etest を作成する方法

Mary-Kate Olsen
リリース: 2025-01-13 06:22:43
オリジナル
350 人が閲覧しました

導入

最近、私は NestJS プロジェクトの単体テストと E2E テストを作成しています。バックエンド プロジェクトのテストを作成するのは初めてですが、そのプロセスがフロントエンド テストの経験とは異なるため、始めるのが大変でした。いくつかの例を見た後、テストへの取り組み方をより明確に理解できたので、同じような混乱に直面している他の人を助けるために、記事を書いて自分の学習を記録し共有する予定です。

さらに、関連するユニットと E2E テストが完了したデモ プロジェクトをまとめました。これは興味深いかもしれません。コードは Github にアップロードされました: https://github.com/woai3c/nestjs-demo.

単体テストと E2E テストの違い

単体テストと E2E テストはソフトウェア テストの方法ですが、目的と範囲が異なります。

単体テストには、ソフトウェア内のテスト可能な最小単位のチェックと検証が含まれます。たとえば、関数やメソッドを 1 つの単位とみなすことができます。単体テストでは、関数のさまざまな入力に対して期待される出力を提供し、その動作の正確さを検証します。単体テストの目的は、関数内のバグを迅速に特定することです。また、バグは簡単に記述でき、迅速に実行できます。

一方、E2E テストでは、実際のユーザー シナリオをシミュレートしてアプリケーション全体をテストすることがよくあります。たとえば、フロントエンドは通常、テストにブラウザまたはヘッドレス ブラウザを使用しますが、バックエンドは API 呼び出しをシミュレートすることによってテストを行います。

NestJS プロジェクト内では、Users モジュールの更新メソッドがユーザーを正しく更新するかどうかを検証するなど、単体テストで特定のサービスやコントローラーのメソッドを評価する場合があります。ただし、E2E テストでは、新しいユーザーの作成からパスワードの更新、最終的にはユーザーの削除に至るまで、複数のサービスとコントローラーが関与する完全なユーザー ジャーニーを検査する場合があります。

単体テストの作成

インターフェイスを含まないユーティリティ関数またはメソッドの単体テストを記述するのは比較的簡単です。必要なのは、さまざまな入力を考慮して、対応するテスト コードを作成することだけです。ただし、インターフェイスが登場すると、状況はさらに複雑になります。例としてコードを使用してみましょう:

async validateUser(
  username: string,
  password: string,
): Promise<UserAccountDto> {
  const entity = await this.usersService.findOne({ username });
  if (!entity) {
    throw new UnauthorizedException('User not found');
  }
  if (entity.lockUntil && entity.lockUntil > Date.now()) {
    const diffInSeconds = Math.round((entity.lockUntil - Date.now()) / 1000);
    let message = `The account is locked. Please try again in ${diffInSeconds} seconds.`;
    if (diffInSeconds > 60) {
      const diffInMinutes = Math.round(diffInSeconds / 60);
      message = `The account is locked. Please try again in ${diffInMinutes} minutes.`;
    }
    throw new UnauthorizedException(message);
  }
  const passwordMatch = bcrypt.compareSync(password, entity.password);
  if (!passwordMatch) {
    // $inc update to increase failedLoginAttempts
    const update = {
      $inc: { failedLoginAttempts: 1 },
    };
    // lock account when the third try is failed
    if (entity.failedLoginAttempts + 1 >= 3) {
      // $set update to lock the account for 5 minutes
      update['$set'] = { lockUntil: Date.now() + 5 * 60 * 1000 };
    }
    await this.usersService.update(entity._id, update);
    throw new UnauthorizedException('Invalid password');
  }
  // if validation is sucessful, then reset failedLoginAttempts and lockUntil
  if (
    entity.failedLoginAttempts > 0 ||
    (entity.lockUntil && entity.lockUntil > Date.now())
  ) {
    await this.usersService.update(entity._id, {
      $set: { failedLoginAttempts: 0, lockUntil: null },
    });
  }
  return { userId: entity._id, username } as UserAccountDto;
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

上記のコードは、auth.service.ts ファイル内のメソッド validateUser であり、主にログイン中にユーザーが入力したユーザー名とパスワードが正しいかどうかを確認するために使用されます。これには次のロジックが含まれています:

  1. ユーザー名に基づいてユーザーが存在するかどうかを確認します。そうでない場合は、401 例外をスローします (404 例外も可能です)。
  2. ユーザーがロックアウトされているかどうかを確認します。その場合は、関連するメッセージを含む 401 例外をスローします。
  3. パスワードを暗号化し、データベース内のパスワードと比較します。正しくない場合は、401 例外をスローします (ログイン試行が 3 回連続して失敗すると、アカウントが 5 分間ロックされます)。
  4. ログインが成功した場合は、以前に失敗したログイン試行回数 (該当する場合) をクリアし、ユーザー ID とユーザー名を次の段階に返します。

ご覧のとおり、validateUser メソッドには 4 つの処理ロジックが含まれており、validateUser 関数全体が正しく動作していることを確認するには、これら 4 つのポイントに対応する単体テスト コードを記述する必要があります。

最初のテストケース

単体テストの作成を開始すると、問題が発生します。findOne メソッドはデータベースと対話する必要があり、ユーザー名を使用してデータベース内で対応するユーザーを検索します。ただし、すべての単体テストでデータベースと対話する必要がある場合、テストは非常に煩雑になります。したがって、これを達成するために偽のデータを模擬することができます。

たとえば、woai3c という名前のユーザーを登録したとします。次に、ログイン中に、 const enity = await this.usersService.findOne({ username }); を通じて validateUser メソッドでユーザー データを取得できます。このコード行が目的のデータを返すことができれば、データベースとの対話がなくても問題はありません。これはモックデータを通じて実現できます。次に、validateUser メソッドに関連するテスト コードを見てみましょう。

async validateUser(
  username: string,
  password: string,
): Promise<UserAccountDto> {
  const entity = await this.usersService.findOne({ username });
  if (!entity) {
    throw new UnauthorizedException('User not found');
  }
  if (entity.lockUntil && entity.lockUntil > Date.now()) {
    const diffInSeconds = Math.round((entity.lockUntil - Date.now()) / 1000);
    let message = `The account is locked. Please try again in ${diffInSeconds} seconds.`;
    if (diffInSeconds > 60) {
      const diffInMinutes = Math.round(diffInSeconds / 60);
      message = `The account is locked. Please try again in ${diffInMinutes} minutes.`;
    }
    throw new UnauthorizedException(message);
  }
  const passwordMatch = bcrypt.compareSync(password, entity.password);
  if (!passwordMatch) {
    // $inc update to increase failedLoginAttempts
    const update = {
      $inc: { failedLoginAttempts: 1 },
    };
    // lock account when the third try is failed
    if (entity.failedLoginAttempts + 1 >= 3) {
      // $set update to lock the account for 5 minutes
      update['$set'] = { lockUntil: Date.now() + 5 * 60 * 1000 };
    }
    await this.usersService.update(entity._id, update);
    throw new UnauthorizedException('Invalid password');
  }
  // if validation is sucessful, then reset failedLoginAttempts and lockUntil
  if (
    entity.failedLoginAttempts > 0 ||
    (entity.lockUntil && entity.lockUntil > Date.now())
  ) {
    await this.usersService.update(entity._id, {
      $set: { failedLoginAttempts: 0, lockUntil: null },
    });
  }
  return { userId: entity._id, username } as UserAccountDto;
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

usersService の findOne メソッドを呼び出してユーザー データを取得するため、テスト コードで usersService の findOne メソッドをモックする必要があります。

import { Test } from '@nestjs/testing';
import { AuthService } from '@/modules/auth/auth.service';
import { UsersService } from '@/modules/users/users.service';
import { UnauthorizedException } from '@nestjs/common';
import { TEST_USER_NAME, TEST_USER_PASSWORD } from '@tests/constants';
describe('AuthService', () => {
  let authService: AuthService; // Use the actual AuthService type
  let usersService: Partial<Record<keyof UsersService, jest.Mock>>;
  beforeEach(async () => {
    usersService = {
      findOne: jest.fn(),
    };
    const module = await Test.createTestingModule({
      providers: [        AuthService,
        {
          provide: UsersService,
          useValue: usersService,
        },
      ],
    }).compile();
    authService = module.get<AuthService>(AuthService);
  });
  describe('validateUser', () => {
    it('should throw an UnauthorizedException if user is not found', async () => {
      await expect(
        authService.validateUser(TEST_USER_NAME, TEST_USER_PASSWORD),
      ).rejects.toThrow(UnauthorizedException);
    });
    // other tests...
  });
});
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

jest.fn() を使用して、実際の usersService.findOne() を置き換える関数を返します。ここで usersService.findOne() を呼び出した場合、戻り値はないため、最初の単体テスト ケースはパスします:

beforeEach(async () => {
    usersService = {
      findOne: jest.fn(), // mock findOne method
    };
    const module = await Test.createTestingModule({
      providers: [        AuthService, // real AuthService, because we are testing its methods
        {
          provide: UsersService, // use mock usersService instead of real usersService
          useValue: usersService,
        },
      ],
    }).compile();
    authService = module.get<AuthService>(AuthService);
  });
ログイン後にコピー
ログイン後にコピー

const エンティティ内の findOne = await this.usersService.findOne({ username }); validateUser メソッドの は戻り値のない偽の関数であり、validateUser メソッドのコードの 2 行目から 4 行目は実行できます。

it('should throw an UnauthorizedException if user is not found', async () => {
  await expect(
    authService.validateUser(TEST_USER_NAME, TEST_USER_PASSWORD),
  ).rejects.toThrow(UnauthorizedException);
});
ログイン後にコピー

401 エラーをスローします。これは予想どおりです。

2 番目のテスト ケース

validateUser メソッドの 2 番目のロジックは、ユーザーがロックされているかどうかを判断するもので、対応するコードは次のとおりです。

if (!entity) {
  throw new UnauthorizedException('User not found');
}
ログイン後にコピー

ご覧のとおり、ユーザー データにロック時間 lockUntil があり、ロック終了時間が現在時刻より大きい場合、現在のアカウントがロックされていると判断できます。したがって、lockUntil フィールドを使用してユーザー データをモックする必要があります:

async validateUser(
  username: string,
  password: string,
): Promise<UserAccountDto> {
  const entity = await this.usersService.findOne({ username });
  if (!entity) {
    throw new UnauthorizedException('User not found');
  }
  if (entity.lockUntil && entity.lockUntil > Date.now()) {
    const diffInSeconds = Math.round((entity.lockUntil - Date.now()) / 1000);
    let message = `The account is locked. Please try again in ${diffInSeconds} seconds.`;
    if (diffInSeconds > 60) {
      const diffInMinutes = Math.round(diffInSeconds / 60);
      message = `The account is locked. Please try again in ${diffInMinutes} minutes.`;
    }
    throw new UnauthorizedException(message);
  }
  const passwordMatch = bcrypt.compareSync(password, entity.password);
  if (!passwordMatch) {
    // $inc update to increase failedLoginAttempts
    const update = {
      $inc: { failedLoginAttempts: 1 },
    };
    // lock account when the third try is failed
    if (entity.failedLoginAttempts + 1 >= 3) {
      // $set update to lock the account for 5 minutes
      update['$set'] = { lockUntil: Date.now() + 5 * 60 * 1000 };
    }
    await this.usersService.update(entity._id, update);
    throw new UnauthorizedException('Invalid password');
  }
  // if validation is sucessful, then reset failedLoginAttempts and lockUntil
  if (
    entity.failedLoginAttempts > 0 ||
    (entity.lockUntil && entity.lockUntil > Date.now())
  ) {
    await this.usersService.update(entity._id, {
      $set: { failedLoginAttempts: 0, lockUntil: null },
    });
  }
  return { userId: entity._id, username } as UserAccountDto;
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

上記のテスト コードでは、オブジェクト lockedUser が最初に定義されており、これには必要な lockUntil フィールドが含まれています。次に、usersService.findOne.mockResolvedValueOnce(lockedUser); によって実現される findOne の戻り値として使用されます。したがって、 validateUser メソッドが実行されると、その中のユーザー データはモック データとなり、2 番目のテスト ケースを正常に通過させます。

単体テストの範囲

単体テスト カバレッジ (コード カバレッジ) は、アプリケーション コードのどれだけが単体テストによってカバーまたはテストされたかを説明するために使用される指標です。通常、これはパーセンテージで表され、考えられるすべてのコード パスのうちどれだけがテスト ケースによってカバーされているかを示します。

単体テストのカバレッジには通常、次のタイプが含まれます:

  • 行カバレッジ: テストでカバーされるコードの行数。
  • 関数カバレッジ: テストの対象となる関数またはメソッドの数。
  • ブランチ カバレッジ: テストでカバーされるコード ブランチの数 (例: if/else ステートメント)。
  • ステートメント カバレッジ: コード内のテストの対象となるステートメントの数。

単体テストのカバレッジは単体テストの品質を測定するための重要な指標ですが、それだけが唯一の指標ではありません。カバレッジ率が高いとコード内のエラーを検出しやすくなりますが、コードの品質が保証されるわけではありません。カバレッジ率が低いということは、テストされていないコードが存在し、検出されていないエラーがある可能性があることを意味する可能性があります。

下の画像は、デモ プロジェクトの単体テスト カバレッジの結果を示しています。

How to write unit tests and Etests for NestJS applications

サービスやコントローラーなどのファイルの場合は、単体テストのカバレッジが高い方が一般的に良いのですが、モジュールのようなファイルの場合は、単体テストを書く必要はなく、意味がないので書くこともできません。上の画像は、単体テスト カバレッジ全体の全体的なメトリクスを表しています。特定の関数のテスト カバレッジを表示したい場合は、プロジェクトのルート ディレクトリにあるcoverage/lcov-report/index.html ファイルを開くことができます。たとえば、validateUser メソッドの特定のテスト状況を確認したいとします。

How to write unit tests and Etests for NestJS applications

ご覧のとおり、validateUser メソッドの元の単体テスト カバレッジは 100% ではなく、実行されなかったコード行がまだ 2 行あります。ただし、4 つの主要な処理ノードには影響しないため、これはあまり重要ではありません。また、一次元的に高いテスト カバレッジを追求すべきではありません。

E2E テストの作成

単体テストでは、模擬データを使用して、各機能が確実にテストできることを確認して、 validateUser() 関数の各機能の単体テストを作成する方法を示しました。 e2E テストでは、実際のユーザー シナリオをシミュレートする必要があるため、テストのためにデータベースに接続する必要があります。したがって、テストする auth.service.ts モジュール内のメソッドはすべてデータベースと対話します。

認証モジュールには主に次の機能が含まれています:

  • 登録
  • ログイン
  • トークンのリフレッシュ
  • ユーザー情報の読み取り
  • パスワードの変更
  • ユーザーの削除

E2E テストでは、ユーザーの登録から削除まで、これら 6 つの機能を 1 つずつテストする必要があります。テスト中に、テストを実行する専用のテスト ユーザーを作成し、テスト データベースに不要な情報が残らないように、完了時にこのテスト ユーザーを削除できます。

async validateUser(
  username: string,
  password: string,
): Promise<UserAccountDto> {
  const entity = await this.usersService.findOne({ username });
  if (!entity) {
    throw new UnauthorizedException('User not found');
  }
  if (entity.lockUntil && entity.lockUntil > Date.now()) {
    const diffInSeconds = Math.round((entity.lockUntil - Date.now()) / 1000);
    let message = `The account is locked. Please try again in ${diffInSeconds} seconds.`;
    if (diffInSeconds > 60) {
      const diffInMinutes = Math.round(diffInSeconds / 60);
      message = `The account is locked. Please try again in ${diffInMinutes} minutes.`;
    }
    throw new UnauthorizedException(message);
  }
  const passwordMatch = bcrypt.compareSync(password, entity.password);
  if (!passwordMatch) {
    // $inc update to increase failedLoginAttempts
    const update = {
      $inc: { failedLoginAttempts: 1 },
    };
    // lock account when the third try is failed
    if (entity.failedLoginAttempts + 1 >= 3) {
      // $set update to lock the account for 5 minutes
      update['$set'] = { lockUntil: Date.now() + 5 * 60 * 1000 };
    }
    await this.usersService.update(entity._id, update);
    throw new UnauthorizedException('Invalid password');
  }
  // if validation is sucessful, then reset failedLoginAttempts and lockUntil
  if (
    entity.failedLoginAttempts > 0 ||
    (entity.lockUntil && entity.lockUntil > Date.now())
  ) {
    await this.usersService.update(entity._id, {
      $set: { failedLoginAttempts: 0, lockUntil: null },
    });
  }
  return { userId: entity._id, username } as UserAccountDto;
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

beforeAll フック関数はすべてのテストが開始される前に実行されるため、ここでテスト アカウント TEST_USER_NAME を登録できます。 afterAll フック関数はすべてのテストが終了した後に実行されるため、ここでテスト アカウント TEST_USER_NAME を削除するのに適しており、また、登録および削除関数のテストにも便利です。

前のセクションの単体テストでは、validateUser メソッドに関連する単体テストを作成しました。実際には、このメソッドはログイン時に実行され、ユーザーのアカウントとパスワードが正しいかどうかを検証します。したがって、この e2E テストでもログイン プロセスを使用して、e2E テスト ケースの作成方法を示します。

ログイン テスト プロセス全体には、次の 5 つの小さなテストが含まれます。

import { Test } from '@nestjs/testing';
import { AuthService } from '@/modules/auth/auth.service';
import { UsersService } from '@/modules/users/users.service';
import { UnauthorizedException } from '@nestjs/common';
import { TEST_USER_NAME, TEST_USER_PASSWORD } from '@tests/constants';
describe('AuthService', () => {
  let authService: AuthService; // Use the actual AuthService type
  let usersService: Partial<Record<keyof UsersService, jest.Mock>>;
  beforeEach(async () => {
    usersService = {
      findOne: jest.fn(),
    };
    const module = await Test.createTestingModule({
      providers: [        AuthService,
        {
          provide: UsersService,
          useValue: usersService,
        },
      ],
    }).compile();
    authService = module.get<AuthService>(AuthService);
  });
  describe('validateUser', () => {
    it('should throw an UnauthorizedException if user is not found', async () => {
      await expect(
        authService.validateUser(TEST_USER_NAME, TEST_USER_PASSWORD),
      ).rejects.toThrow(UnauthorizedException);
    });
    // other tests...
  });
});
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

これら 5 つのテストは次のとおりです:

  1. ログインに成功すると、200 を返します
  2. ユーザーが存在しない場合は、401 例外をスローします
  3. パスワードまたはユーザー名が指定されていない場合は、400 例外をスローします
  4. 間違ったパスワードでログインすると、401 例外がスローされます
  5. アカウントがロックされている場合は、401 例外をスローします

それでは、e2E テストの作成を開始しましょう:

beforeEach(async () => {
    usersService = {
      findOne: jest.fn(), // mock findOne method
    };
    const module = await Test.createTestingModule({
      providers: [        AuthService, // real AuthService, because we are testing its methods
        {
          provide: UsersService, // use mock usersService instead of real usersService
          useValue: usersService,
        },
      ],
    }).compile();
    authService = module.get<AuthService>(AuthService);
  });
ログイン後にコピー
ログイン後にコピー

e2E テスト コードの作成は比較的簡単です。インターフェイスを呼び出して結果を確認するだけです。たとえば、ログイン テストが成功した場合、返される結果が 200 であることを確認するだけです。

最初の 4 つのテストは非常に簡単です。次に、アカウントがロックされているかどうかを確認する、少し複雑な e2E テストを見てみましょう。

async validateUser(
  username: string,
  password: string,
): Promise<UserAccountDto> {
  const entity = await this.usersService.findOne({ username });
  if (!entity) {
    throw new UnauthorizedException('User not found');
  }
  if (entity.lockUntil && entity.lockUntil > Date.now()) {
    const diffInSeconds = Math.round((entity.lockUntil - Date.now()) / 1000);
    let message = `The account is locked. Please try again in ${diffInSeconds} seconds.`;
    if (diffInSeconds > 60) {
      const diffInMinutes = Math.round(diffInSeconds / 60);
      message = `The account is locked. Please try again in ${diffInMinutes} minutes.`;
    }
    throw new UnauthorizedException(message);
  }
  const passwordMatch = bcrypt.compareSync(password, entity.password);
  if (!passwordMatch) {
    // $inc update to increase failedLoginAttempts
    const update = {
      $inc: { failedLoginAttempts: 1 },
    };
    // lock account when the third try is failed
    if (entity.failedLoginAttempts + 1 >= 3) {
      // $set update to lock the account for 5 minutes
      update['$set'] = { lockUntil: Date.now() + 5 * 60 * 1000 };
    }
    await this.usersService.update(entity._id, update);
    throw new UnauthorizedException('Invalid password');
  }
  // if validation is sucessful, then reset failedLoginAttempts and lockUntil
  if (
    entity.failedLoginAttempts > 0 ||
    (entity.lockUntil && entity.lockUntil > Date.now())
  ) {
    await this.usersService.update(entity._id, {
      $set: { failedLoginAttempts: 0, lockUntil: null },
    });
  }
  return { userId: entity._id, username } as UserAccountDto;
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

ユーザーが 3 回連続でログインに失敗すると、アカウントはロックされます。したがって、このテストでは、テスト アカウント TEST_USER_NAME を使用できません。テストが成功すると、このアカウントはロックされ、次のテストを続行できなくなります。特にアカウント ロックをテストするために別の新しいユーザー TEST_USER_NAME2 を登録し、テストが成功したらこのユーザーを削除する必要があります。ご覧のとおり、この e2E テストのコードは非常に充実しており、セットアップと分解に多くの作業が必要ですが、実際のテスト コードは次の数行だけです。

import { Test } from '@nestjs/testing';
import { AuthService } from '@/modules/auth/auth.service';
import { UsersService } from '@/modules/users/users.service';
import { UnauthorizedException } from '@nestjs/common';
import { TEST_USER_NAME, TEST_USER_PASSWORD } from '@tests/constants';
describe('AuthService', () => {
  let authService: AuthService; // Use the actual AuthService type
  let usersService: Partial<Record<keyof UsersService, jest.Mock>>;
  beforeEach(async () => {
    usersService = {
      findOne: jest.fn(),
    };
    const module = await Test.createTestingModule({
      providers: [        AuthService,
        {
          provide: UsersService,
          useValue: usersService,
        },
      ],
    }).compile();
    authService = module.get<AuthService>(AuthService);
  });
  describe('validateUser', () => {
    it('should throw an UnauthorizedException if user is not found', async () => {
      await expect(
        authService.validateUser(TEST_USER_NAME, TEST_USER_PASSWORD),
      ).rejects.toThrow(UnauthorizedException);
    });
    // other tests...
  });
});
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

e2E テスト コードの作成は比較的簡単です。模擬データやテスト カバレッジを考慮する必要はありません。システムプロセス全体が期待どおりに実行されれば十分です。

テストを書くかどうか

可能であれば、通常はテストを書くことをお勧めします。これにより、システムの堅牢性、保守性、開発効率が向上します。

システムの堅牢性の強化

コードを記述するときは、通常、コア機能が適切に動作することを確認するために、通常の入力でのプログラム フローに重点を置きます。ただし、異常な入力などの特殊なケースは見落とされることがよくあります。テストを書くとこれが変わります。このような場合にどのように対処するかを検討し、適切に対応することでクラッシュを防ぐ必要があります。テストを書くことは間接的にシステムの堅牢性を向上させると言えます。

保守性の向上

包括的なテストを含む新しいプロジェクトを引き継ぐのは、とても楽しいことです。これらはガイドとして機能し、さまざまな機能をすぐに理解するのに役立ちます。関数のコードを 1 行ずつ確認することなく、テスト コードを見るだけで、各関数の期待される動作と境界条件を簡単に把握できます。

開発効率の向上

しばらく更新されていなかったプロジェクトが突然新しい要件を受け取ったと想像してください。変更を加えた後、バグが発生するのではないかと心配になるかもしれません。テストがなければ、プロジェクト全体を手動で再度テストする必要があり、時間が無駄になり非効率的になります。完全なテストでは、コードの変更が既存の機能に影響を与えているかどうかを 1 つのコマンドで知ることができます。エラーがあった場合でも、すぐに特定して対処できます。

テストを書いてはいけない場合は?

短期プロジェクト要件の反復が非常に速いプロジェクトの場合、テストを作成することはお勧めできません。たとえば、イベントが終了すると役に立たなくなるイベント用のプロジェクトにはテストが必要ありません。また、要件の反復が非常に速いプロジェクトの場合、テストを作成すると開発効率が向上すると言いましたが、それは関数の反復が遅いという前提に基づいています。完了した関数が 1 ~ 2 日で変更される場合は、関連するテスト コードを書き直す必要があります。したがって、テストを作成するのは非常に時間がかかり、労力を費やす価値がないため、テストをまったく作成せず、代わりにテスト チームに頼る方が良いでしょう。

結論

NestJS プロジェクトの単体テストと e2E テストの作成方法を詳しく説明した後、テストの重要性を繰り返しておきたいと思います。システムの堅牢性、保守性、開発効率を向上させることができます。テストを作成する機会がない場合は、自分で練習プロジェクトを開始するか、オープンソース プロジェクトに参加してコードを貢献することをお勧めします。オープンソース プロジェクトには通常、より厳しいコード要件があります。コードに貢献するには、新しいテスト ケースを作成したり、既存のテスト ケースを変更したりすることが必要になる場合があります。

参考資料

  • NestJS: 効率的でスケーラブルな Node.js サーバー側アプリケーションを構築するためのフレームワーク。
  • MongoDB: データ ストレージに使用される NoSQL データベース。
  • Jest: JavaScript と TypeScript のテスト フレームワーク。
  • スーパーテスト: HTTP サーバーをテストするためのライブラリ。

以上がNestJS アプリケーションの単体テストと Etest を作成する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:dev.to
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート