unit-testing - 如何对 NestJS 的自定义 CacheInterceptor 进行单元测试?

标签 unit-testing testing nestjs

我编写了一个自己的 CacheInterceptor 来缓存 POST 请求,并考虑 Accept-Language header 。当然,我想对其进行单元测试,但我不知道如何正确执行此操作,因为 trackBy 方法需要 ExecutionContext 并且该方法使用 httpAdapterHostreflector 字段。 有人以前这样做过并且知道如何实现完整的测试覆盖率吗?

编辑:这是CacheInterceptor的代码

import {
    CACHE_KEY_METADATA,
    CacheInterceptor,
    ExecutionContext,
    Injectable,
} from '@nestjs/common';

import { createHash } from 'crypto';

@Injectable()
export class MyCacheInterceptor extends CacheInterceptor {
    trackBy(context: ExecutionContext): string | undefined {
        const httpAdapter = this.httpAdapterHost.httpAdapter;
        const cacheMetadata = this.reflector.get(CACHE_KEY_METADATA, context.getHandler());

        const request = context.switchToHttp().getRequest();

        return [
            cacheMetadata,
            httpAdapter.getRequestUrl(request),
            JSON.stringify(request.body),
            request.headers['accept-language'],
        ]
            .reduce(
                (hash, somethingToHash) => (
                    hash.update(
                        somethingToHash
                            ? Buffer.from(somethingToHash)
                            : Buffer.alloc(0)
                    )
                ),
                createHash('md5'),
            )
            .digest('hex');
    }
}

最佳答案

请记住,以下示例是单独测试拦截器。您的用例可能需要进行一些调整,但总体方法应该是有效的。

  1. 我将使用构造函数注入(inject)缓存和反射器依赖项:
@Injectable()
export class MyCacheInterceptor extends CacheInterceptor {
  constructor(
    @Inject(CACHE_MANAGER) protected readonly cacheManager: Cache,
    @Inject(Reflector) protected readonly reflector: Reflector
  ) {
    super(cacheManager, reflector);
  }

  trackBy(context: ExecutionContext): string | undefined {

// ...
// ...
  • 您的测试可能如下所示:
  • describe("MyCacheInterceptor", () => {
      let interceptor: MyCacheInterceptor;
    
      beforeEach(async () => {
        const module = await Test.createTestingModule({
          imports: [CacheModule.register()],
          providers: [
            { provide: CACHE_MANAGER, useValue: {} },
            { provide: Reflector, useValue: { get: () => "hello" } },
            MyCacheInterceptor,
          ],
        }).compile();
    
        // see issue: https://github.com/nestjs/nest/issues/8076
        module.createNestApplication();
    
        interceptor = module.get(MyCacheInterceptor);
      });
    
      it("creates", () => {
        expect(interceptor).toBeTruthy();
      });
    
      it("tracks something", () => {
        const mockExecutionContext: ExecutionContext = createMock<ExecutionContext>(
          {
            getHandler: () => ({}),
            switchToHttp: () => ({
              getRequest: () => ({
                url: "/test-url",
                originalUrl: "/test-url",
                method: "GET",
                body: {
                  someKey: "someValue",
                },
                headers: {
                  "accept-language": "en",
                },
              }),
            }),
          }
        );
    
        const result = interceptor.trackBy(mockExecutionContext);
    
        expect(result).toBe("d4f8ad8ba612cda9a5fda09cc244120c");
      });
    });
    
  • 有一种模拟 httpAdapterHost(以及 cacheManagerreflector)的方法:
  • (interceptor["httpAdapterHost"] as any) = {
      httpAdapter: { getRequestUrl: () => "hello" },
    };
    

    我认为这是一种反模式,因为您不应该 mock /监视内部方法和属性。但是,如果您检查 this GitHub 问题,您会发现没有好的或正确的方法来模拟 HttpAdapterHost,因此在这种情况下,打破它可能是一个很好的规则。

  • createMock 来自@golevelup/ts-jest
  • 关于unit-testing - 如何对 NestJS 的自定义 CacheInterceptor 进行单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72885605/

    相关文章:

    node.js - npm 运行构建中的 Nestjs "Reached heap limit Allocation failed - JavaScript heap out of memory"

    postgresql - NestJS => PostgresQL : Error: getaddrinfo EAI_AGAIN postgres at GetAddrInfoReqWrap. 查找

    unit-testing - Xna:模拟 Texture2D

    internet-explorer - 如果我没有安装 MS Edge Web 浏览器,如何在它上测试我的网站?

    php - 模拟对象和仅设置值有什么区别

    java - 如何使用Java捕获网络流量并在不使用代理的情况下获取文件类型?

    reactjs - 在 react 测试中的 fireEvent.click 之后将 radio 的 aria-checked 属性设置为 true

    nestjs - @Get DTO 在 NestJs 中有多个参数

    c# - 如何打开测试项目代码文件夹中的文件? (Visual Studio 2008 和 .NET C#)

    python - 更改相关命令后如何自动运行 py.test?