e2e 如何与 guard nestjs
Posted
技术标签:
【中文标题】e2e 如何与 guard nestjs【英文标题】:How e2e with guard nestjs 【发布时间】:2020-02-10 01:16:59 【问题描述】:我想使用nestjs 对一个名为/users
的端点进行e2e,但出现错误。我对如何让警卫通过测试感到疑惑。
第一个错误
Nest 无法解析 UserModel (?) 的依赖关系。请确保 索引 [0] 处的参数 DatabaseConnection 在 MongooseModule 上下文。
第二个错误
预期 200“OK”,得到 401“Unauthorized”
App.module
@Module(
imports: [
MongooseModule.forRootAsync(
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => (
uri: configService.mongoUri,
useNewUrlParser: true,
),
inject: [ConfigService],
),
GlobalModule,
UsersModule,
AuthModule,
PetsModule,
RestaurantsModule,
ConfigModule,
],
controllers: [],
providers: [],
)
export class AppModule implements NestModule
configure(consumer: MiddlewareConsumer)
consumer
.apply(TokenDataMiddleware)
.forRoutes( path: '*', method: RequestMethod.ALL );
用户服务
@Injectable()
export class UsersService
constructor(
@InjectModel('User') private readonly userModel: Model<UserDocument>,
private readonly utilsService: UtilsService,
private readonly configService: ConfigService,
)
async getAllUsers(): Promise<UserDocument[]>
const users = this.userModel.find().lean().exec();
return users;
控制器
@Controller('users')
export class UsersController
constructor(private readonly usersService: UsersService, private readonly utilsService: UtilsService)
@Get()
@ApiBearerAuth()
@UseGuards(JwtAuthGuard)
async users()
const users = await this.usersService.getAllUsers();
return users;
e2e 文件
describe('UsersController (e2e)', () =>
let app: INestApplication;
beforeAll(async () =>
const testAppModule: TestingModule = await Test.createTestingModule(
imports: [AppModule, GlobalModule,
UsersModule,
AuthModule,
PetsModule,
RestaurantsModule,
ConfigModule],
providers: [],
).compile();
app = testAppModule.createNestApplication();
await app.init();
);
it('GET all users from API', async () =>
// just mocked users;
const users = getAllUsersMock.buildList(2);
const response = await request(app.getHttpServer())
.get('/users')
.expect(200);
);
afterAll(async () =>
await app.close();
);
);
【问题讨论】:
【参考方案1】:在单元测试中,您测试单个单元(服务、控制器等),这意味着您导入一个单元并模拟其所有依赖项。然而,在 e2e 测试中,您想要测试您的整个应用程序,因此您应该导入根模块 (AppModule
) 而不是单个单元或模块。有时您可能想要模拟应用程序的特定部分,例如数据库或第 3 方 API;你可以用overrideProvider
等来做到这一点。
在您的情况下,您可能缺少从您的AppModule
导入的MongooseModule
的forRoot
。导入 AppModule,而不是重组应用程序的某些部分:
await Test.createTestingModule(
imports: [AppModule],
).compile()
.overrideProvider(HttpService)
.useValue(httpServiceMock);
如果您的 API 受到保护,您需要对其进行身份验证。您可以通过编程方式创建 JWT,也可以使用您的 API。我假设您在以下示例中有一个用于身份验证的端点:
const loginResponse = await request(app.getHttpServer())
.post('/auth/login')
.send( username: 'user', password: '123456' )
.expect(201);
// store the jwt token for the next request
const jwt = loginResponse.body;
await request(app.getHttpServer())
.get('/users')
// use the jwt to authenticate your request
.set('Authorization', 'Bearer ' + jwt)
.expect(200)
.expect(res => expect(res.body.users[0])
.toMatchObject( username: 'user' ));
【讨论】:
您好,感谢您的回答,我用您的更改更新了问题(它有效),但保留我关于模拟 jwt 令牌的问题以通过 JwtAuthGuard。谢谢! @anthonywillismuñoz 查看我的编辑。由于您的 API 受到保护,因此 401 错误符合预期。测试未经身份验证的请求无法访问您的 API 实际上很好。要测试受保护的资源,您必须设置 Authorization 标头,请参见示例。此外,您不需要导入所有模块。 仅 导入 AppModule。它本身将导入所有其他模块。 @Kim Kern 什么是 httpServiceMock?我遇到了同样的问题,无法理解 @MegaRoks 看看这个关于如何创建模拟的线程:***.com/a/55366343/4694994以上是关于e2e 如何与 guard nestjs的主要内容,如果未能解决你的问题,请参考以下文章
NestJS:如何在从 JWT AuthGuard 扩展的 GraphQL 自定义 Guard 中从请求中获取用户
如何使用 NestJS 和 class-validator 手动测试输入验证