4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

NestJSでGuardsのテストを書く

Posted at

日本語記事はあまりヒットしなかったので、メモ。
調べたところ、いくつかアプローチはありそうでした。

テスト用のモジュールに組み込んでアプリを起動しe2e的にテストする

function createTestModule(guard) {
  return Test.createTestingModule({
    imports: [AppModule],
    providers: [
      {
        provide: APP_GUARD,
        useValue: guard,
      },
    ],
  }).compile();
}

describe('Guards', () => {
  let app: INestApplication;

  it(`should prevent access (unauthorized)`, async () => {
    app = (await createTestModule(new AuthGuard())).createNestApplication();

    await app.init();
    return request(app.getHttpServer()).get('/hello').expect(401);
  });
});

nestjsのサンプルコードのテストになります。
特にモック等を使うこともなく、一番シンプルな方法だと思います。

複数のGuardsを利用する場合等を考えると、実際にリクエストするという点ではユースケースと合わないテストを書くことになります。モジュールの単体テストにする方がより良いと思います。

リクエストを自力でmockして単体テストする

const mockExecutionContext: Partial<
  Record<
    jest.FunctionPropertyNames<ExecutionContext>,
    jest.MockedFunction<any>
  >
> = {
  switchToHttp: jest.fn().mockReturnValue({
    getRequest: jest.fn(),
    getResponse: jest.fn(),
  }),
};

テスト対象となる canActive() メソッドはbooleanになるためmockに対して何が呼ばれたか期待するテストを書くことになります。

必要なものを必要なだけ毎回自力で作る方法になります。場合によっては冗長になる?

NestJSのテスト用のライブラリを使ってリクエストをmockして単体テストする

import { createMock } from '@golevelup/ts-jest';
import { ExecutionContext, UnauthorizedException } from '@nestjs/common';

import { AuthenticatedGuard } from '@/common/guards';

describe('AuthenticatedGuard', () => {
  describe('canActivate', () => {
    it('should return true when user is authenticated', () => {
      const mockContext = createMock<ExecutionContext>();
      mockContext.switchToHttp().getRequest.mockReturnValue({
        // method attached to `req` instance by Passport lib
        isAuthenticated: () => true,
      });

      const canActivate = authenticatedGuard.canActivate(mockContext);

      expect(canActivate).toBe(true);
    });
  });
});

利用するのは @golevelup/ts-jest で、Guardに渡すcontextをmockします。
自力で書くよりはシンプルに書ける印象です。

NestJS公式のライブラリではありませんが、

A collection of Badass modules and utilities to help you level up your NestJS application.

というだけあり、 https://github.com/golevelup/nestjs の配下に ts-jest の他にも便利そうなライブラリが多くあり興味を持ちました。

実際に利用したもの

3つ目に書いた @golevelup/ts-jest を利用しました。
JWTを検証・デコードした結果をリクエストに入れて後段に渡したりする場合、1つ目の方法だとセットしたことをテストできません。
また自力でリクエストのmockを書くのもの辛かったため、3つ目の方法を採用しました。

どれにするかは実装やケースによると思いますが、参考になれば。

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?