【问题标题】:NestJS Mocking a Mixin that returns a GuardNestJS 模拟返回 Guard 的 Mixin
【发布时间】:2021-05-08 21:34:07
【问题描述】:

我希望对我遇到的问题有所了解。

我有一个可以产生守卫的 mixin。生成的守卫使用注入的服务。这是 mixin 的代码:

import {
  CanActivate,
  ExecutionContext,
  Injectable,
  mixin,
} from '@nestjs/common';
import { GqlExecutionContext } from '@nestjs/graphql';
import { AccountService } from 'src/modules/account/account.service';

export const ForAccountGuard = (
  paramName: string,
  { required = false }: { required?: boolean } = {}
) => {
  @Injectable()
  class _ForAccountGuard implements CanActivate {
    constructor(private readonly accountService: AccountService) {}

    async canActivate(context: ExecutionContext) {
      const ctx = GqlExecutionContext.create(context);
      const accountId = ctx.getArgs()[paramName];
      const currentUser = ctx.getContext().user;

      if (required && !accountId) {
        return false;
      }

      if (accountId) {
        const account = await this.accountService.findUserAccount(
          accountId,
          currentUser.id
        );
        return !!account;
      }

      return true;
    }
  }

  return mixin(_ForAccountGuard);
};

在我对使用此 mixin 作为保护的解析器的测试中,我正在执行以下操作:

  @Query(() => [PropertyEntity])
  @UseGuards(ForAccountGuard('accountId'))
  async allProperties(@Args() { accountId }: AllPropertiesArgs) {
    // <implementation removed>
  }

所以,我遇到的问题是在运行测试时出现以下错误:

    Cannot find module 'src/modules/account/account.service' from 'modules/common/guards/for-account.guard.ts'

    Require stack:
      modules/common/guards/for-account.guard.ts
      modules/property/property.resolver.spec.ts

看起来注入的 AccountService 没有被解析。

我不确定如何告诉 Nest 的测试模块覆盖作为 mixin 的守卫。我一直在尝试这样,但它似乎不起作用:

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [
        PropertyResolver,
        ...
      ],
    })
      .overrideGuard(ForAccountGuard)
      .useValue(createMock<typeof ForAccountGuard>())
      .compile();
    );
  });

那么,我应该如何模拟一个作为 mixin 的守卫?

【问题讨论】:

  • 您使用的是绝对导入还是相对导入?如果您使用的是绝对(导入以src/ 开头),那么您需要将正确的映射添加到jest.config.js 文件中

标签: unit-testing dependency-injection nestjs


【解决方案1】:

好的,经过一番修改,我想出了一个解决方案。

放弃overrideGuard 方法并直接使用整个mixin 的jest.mock 似乎可以解决问题。

所以,我创建了一个模拟:

import { CanActivate, Injectable, mixin } from '@nestjs/common';

export const mockForAccountGuard = () => {
  @Injectable()
  class _ForAccountGuardMock implements CanActivate {
    canActivate() {
      return true;
    }
  }

  return mixin(_ForAccountGuardMock);
};

然后我用jest.mock 模拟出来:

// in my test file

import { mockForAccountGuard } from '../common/guards/__mocks__/for-account.guard';
import { ForAccountGuard } from '../common/guards/for-account.guard';

jest.mock('../common/guards/for-account.guard', () => ({
  ForAccountGuard: mockForAccountGuard,
}));

...

describe('PropertyResolver', () => {
  ...
  beforeEach(() => {
    ...
    const module: TestingModule = await Test.createTestingModule({
      ...
    }).compile() // note, not using overrideGuards here
  });
})

这似乎可以解决问题!

【讨论】:

    猜你喜欢
    • 2016-12-11
    • 2020-02-10
    • 2021-10-12
    • 2019-02-21
    • 2015-10-21
    • 2020-06-30
    • 2020-06-03
    • 1970-01-01
    • 2019-08-18
    相关资源
    最近更新 更多