我对 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。 我确信,要么我做错了什么,要么我错过了一些小事。 如果我需要任何进一步的信息,请随时告诉我 我提前感谢大家的帮助
花了一天时间解决这个问题,我想我现在知道该怎么做了。当您使用
APP_GUARD
启用全局防护时,您需要使用 overrideProvider
而不是 overrideGuard
,因为 APP_GUARD
实际上不是防护,防护是作为提供者注入的。
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule],
providers: [],
})
.overrideProvider(MyGuard)
.useValue({ canActivate })
.compile();
在深入研究 Nest 的核心和测试模块后,我找到了让它以“干净的方式”工作的答案。
您需要在模块中利用
useExisting
将您的守卫别名为提供者
@Module({
providers: [
FooGuard,
{
provide: APP_GUARD,
useExisting: FooGuard,
}
]
})
class FooModule {}
现在在您的测试文件中您可以使用
.overrideProvider
(不是 .overrideGuard
)