Nestjs:测试文件中的 overrideGuardguard 不起作用

问题描述 投票:0回答:2

我对 Nestjs 和笑话都很陌生。 我试图超越守卫,但它不起作用。所以我的文件夹结构是: “src/app.module.ts”,“src/modules/auth/guards/myfile-guard.ts”,“src/modules/auth/auth.module.ts”,“src/modules/user/user.controller .ts”和“src/modules/user”包含所有用户相关文件。我正在测试用户控制器的 e2e 测试,它有一个获取路由“/users”,它需要用户登录,它是由守卫确定的,然后提到这个守卫是在“src/modules/auth/auth”中完成的.module.ts"如下:

@Module({
  imports: [],
  controllers: [AuthController],
  providers: [
    {
      provide: APP_GUARD,
      useClass: IsAuthenticatedGuard,
    },
    AuthService,
  ],
  exports: [AuthService],
})
export class AuthModule {}

我的守卫文件:“src/modules/auth/guards/myfile-guard.ts”看起来像:

@Injectable()
export class MyGuard extends AuthGuard('local')
  implements CanActivate {
  constructor(private readonly reflector: Reflector) {
    super();
  }
  public canActivate(context: ExecutionContext): boolean {
    const isPublic = this.reflector.get<boolean>(
      'isPublic',
      context.getHandler(),
    );
    if (isPublic) {
      return true;
    }
    const request = context.switchToHttp().getRequest<Request>();
    const isAuthenticated = request.isAuthenticated();
    if (!isAuthenticated) {
      throw new UnauthorizedException();
    }
    return true;
  }
}

“src/app.module.ts”文件,我有以下代码:

@Module({
  imports: [
    AuthModule,
    UserModule,
  ],
  controllers: [AppController],
  providers: [],
})
export class AppModule {}

“src/modules/user/user.controller.ts” 文件中,我有以下代码:

@Controller('users')
export class UserController {
  constructor(private readonly userService: UserService) {}
  @Get()
  async getUsers(): Promise<User[]> {
    return this.userService.findUsers();
  }
}

“src/test/user-e2e-spec.ts” 文件中,我有以下代码:

import { MyGuard } from '../src/modules/auth/guards/myfile-guard';
import { AppModule } from '../src/app.module';
describe('UserController (e2e)', () => {
  let app: INestApplication;
  const canActivate = jest.fn(() => true);
  beforeEach(async () => {
    const moduleFixture: TestingModule = await Test.createTestingModule({
      imports: [AppModule],
      providers: [],
    })
      .overrideGuard(MyGuard)
      .useValue({ canActivate })
      .compile();
    app = moduleFixture.createNestApplication();
    jest.resetAllMocks();
    await app.init();
  });
  describe('@Get()', () => {
    const requestUrl = '/users';
    canActivate.mockReturnValueOnce(true);
    it('returns list of users', async () => {
      return request(app.getHttpServer())
        .get(requestUrl)
        .expect(200);
    });
  });
});

当我运行测试时,在 200 的地方,我总是得到 401 未经授权,这意味着“MyGuard”没有被 {canActivate} 覆盖,我什至在 MyGuard 类中做了 console.log,它总是在那里,其中不应该, 我尝试搜索与相同相关的不同问题,其中很少有帮助我在这个阶段达到的,下面是我已经访问过并且对我有帮助的一些链接: Nestjs 单元测试 - 模拟方法守卫 使用不同的守卫与nestJS进行控制器集成测试

但我仍然无法让它按照需要工作,它从模拟或覆盖的 canActivate 返回 true。 我确信,要么我做错了什么,要么我错过了一些小事。 如果我需要任何进一步的信息,请随时告诉我 我提前感谢大家的帮助

jestjs mocking overriding nestjs e2e-testing
2个回答
0
投票

花了一天时间解决这个问题,我想我现在知道该怎么做了。当您使用

APP_GUARD
启用全局防护时,您需要使用
overrideProvider
而不是
overrideGuard
,因为
APP_GUARD
实际上不是防护,防护是作为提供者注入的。

const moduleFixture: TestingModule = await Test.createTestingModule({
      imports: [AppModule],
      providers: [],
    })
      .overrideProvider(MyGuard)
      .useValue({ canActivate })
      .compile();

0
投票

在深入研究 Nest 的核心和测试模块后,我找到了让它以“干净的方式”工作的答案。

您需要在模块中利用

useExisting
将您的守卫别名为提供者

@Module({
  providers: [
    FooGuard,
    {
      provide: APP_GUARD,
      useExisting: FooGuard,
    }
  ]
})
class FooModule {}

现在在您的测试文件中您可以使用

.overrideProvider
(不是
.overrideGuard

© www.soinside.com 2019 - 2024. All rights reserved.