簡體   English   中英

Nestjs 單元測試 - 模擬方法保護

[英]Nestjs unit-test - mock method guard

我已經開始使用 NestJS 並且有一個關於模擬單元測試的守衛的問題。 我正在嘗試測試一個基本的 HTTP controller ,它有一個方法 Guard 附加到它。

當我向 Guard 注入服務時,我的問題就開始了(我需要為 Guard 使用ConfigService )。

運行測試時,DI 無法解析 Guard

  ● AppController › root › should return "Hello World!"

    Nest can't resolve dependencies of the ForceFailGuard (?). Please make sure that the argument at index [0] is available in the _RootTestModule context.

我的力量失敗守衛:

import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { ConfigService } from './config.service';

@Injectable()
export class ForceFailGuard implements CanActivate {

  constructor(
    private configService: ConfigService,
  ) {}

  canActivate(context: ExecutionContext) {
    return !this.configService.get().shouldFail;
  }
}

規范文件:

import { CanActivate } from '@nestjs/common';
import { Test, TestingModule } from '@nestjs/testing';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ForceFailGuard } from './force-fail.guard';

describe('AppController', () => {
  let appController: AppController;

  beforeEach(async () => {

    const mock_ForceFailGuard = { CanActivate: jest.fn(() => true) };

    const app: TestingModule = await Test
      .createTestingModule({
        controllers: [AppController],
        providers: [
          AppService,
          ForceFailGuard,
        ],
      })
      .overrideProvider(ForceFailGuard).useValue(mock_ForceFailGuard)
      .overrideGuard(ForceFailGuard).useValue(mock_ForceFailGuard)
      .compile();

    appController = app.get<AppController>(AppController);
  });

  describe('root', () => {

    it('should return "Hello World!"', () => {
      expect(appController.getHello()).toBe('Hello World!');
    });

  });
});

我無法找到有關此問題的示例或文檔。 我錯過了什么還是這是一個真正的問題?

感謝任何幫助,謝謝。

我已經開始使用 NestJS 並且有一個關於模擬單元測試的守衛的問題。 我正在嘗試測試一個基本的 HTTP controller ,它有一個方法 Guard 附加到它。

當我向 Guard 注入服務時,我的問題就開始了(我需要ConfigService用於 Guard)。

運行測試時,DI 無法解析 Guard

  ● AppController › root › should return "Hello World!"

    Nest can't resolve dependencies of the ForceFailGuard (?). Please make sure that the argument at index [0] is available in the _RootTestModule context.

我的力量失敗守衛:

import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { ConfigService } from './config.service';

@Injectable()
export class ForceFailGuard implements CanActivate {

  constructor(
    private configService: ConfigService,
  ) {}

  canActivate(context: ExecutionContext) {
    return !this.configService.get().shouldFail;
  }
}

規范文件:

import { CanActivate } from '@nestjs/common';
import { Test, TestingModule } from '@nestjs/testing';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ForceFailGuard } from './force-fail.guard';

describe('AppController', () => {
  let appController: AppController;

  beforeEach(async () => {

    const mock_ForceFailGuard = { CanActivate: jest.fn(() => true) };

    const app: TestingModule = await Test
      .createTestingModule({
        controllers: [AppController],
        providers: [
          AppService,
          ForceFailGuard,
        ],
      })
      .overrideProvider(ForceFailGuard).useValue(mock_ForceFailGuard)
      .overrideGuard(ForceFailGuard).useValue(mock_ForceFailGuard)
      .compile();

    appController = app.get<AppController>(AppController);
  });

  describe('root', () => {

    it('should return "Hello World!"', () => {
      expect(appController.getHello()).toBe('Hello World!');
    });

  });
});

我無法找到有關此問題的示例或文檔。 我錯過了什么還是這是一個真正的問題?

感謝任何幫助,謝謝。

如果除了控制器單元測試之外,您還需要/想要對您的自定義防護實現進行單元測試,您可以使用類似於下面的測試以預期錯誤等

// InternalGuard.ts
@Injectable()
export class InternalTokenGuard implements CanActivate {
  constructor(private readonly config: ConfigService) {}

  public async canActivate(context: ExecutionContext): Promise<boolean> {
    const token = this.config.get('internalToken');

    if (!token) {
      throw new Error(`No internal token was provided.`);
    }

    const request = context.switchToHttp().getRequest();
    const providedToken = request.headers['authorization'];

    if (token !== providedToken) {
      throw new UnauthorizedException();
    }

    return true;
  }
}

還有你的規范文件

beforeEach(async () => {
  const module: TestingModule = await Test.createTestingModule({
    controllers: [],
    providers: [
      InternalTokenGuard,
      {
        provide: ConfigService,
        useValue: {
          get: jest.fn((key: string) => {
            if (key === 'internalToken') {
              return 123;
            }
            return null;
          }),
        },
      },
    ],
  }).compile();

  config = module.get<ConfigService>(ConfigService);
  guard = module.get<InternalTokenGuard>(InternalTokenGuard);
});

it('should throw UnauthorizedException when token is not Bearer', async () => {
  const context = {
    getClass: jest.fn(),
    getHandler: jest.fn(),
    switchToHttp: jest.fn(() => ({
      getRequest: jest.fn().mockReturnValue({
        headers: {
          authorization: 'providedToken',
        },
      }),
    })),
  } as any;

  await expect(guard.canActivate(context)).rejects.toThrow(
    UnauthorizedException,
  );
  expect(context.switchToHttp).toHaveBeenCalled();
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM