【问题标题】:Controller integration testing with nestJS using different guards使用不同守卫的 NestJS 进行控制器集成测试
【发布时间】:2021-02-26 04:26:45
【问题描述】:

我正在尝试使用 NestJs 作为后端框架来开发应用程序。目前我正在为控制器编写一些集成测试。

这是我第一个使用 typescript 的项目,我通常使用 Java/Spring,但我想学习并尝试使用 nestJs。

我使用不同的守卫来访问其他端点。在这种情况下,我有一个 AuthGuardRolesGuard

为了使其余端点工作,我只需在 TestingModuleBuilder 中添加类似这样的内容:

        .overrideGuard(AuthGuard())
        .useValue({ canActivate: () => true })

关键是,是否可以为每个测试定义或覆盖此保护,以检查在未定义保护或不允许保护的情况下请求是否失败?

我的测试代码如下:

describe('AuthController integration tests', () => {
let userRepository: Repository<User>
let roleRepository: Repository<Role>
let app: INestApplication
beforeAll(async () => {
    const module = await Test.createTestingModule({
        imports: [
            AuthModule,
            TypeOrmModule.forRoot(typeOrmConfigTest),
            PassportModule.register({ defaultStrategy: 'jwt' }),
            JwtModule.register({
                secret: jwtConfig.secret,
                signOptions: {
                    expiresIn: jwtConfig.expiresIn
                }
            })
        ]
    })
        .overrideGuard(AuthGuard())
        .useValue({ canActivate: () => true })
        .overrideGuard(RolesGuard)
        .useValue({ canActivate: () => true })
        .compile()
    app = module.createNestApplication()
    await app.init()

    userRepository = module.get('UserRepository')
    roleRepository = module.get('RoleRepository')

    const initializeDb = async () => {
        const roles = roleRepository.create([
            { name: RoleName.ADMIN },
            { name: RoleName.TEACHER },
            { name: RoleName.STUDENT }
        ])
        await roleRepository.save(roles)
    }

    await initializeDb()
})

afterAll(async () => {
    await roleRepository.query(`DELETE FROM roles;`)
    await app.close()
})

afterEach(async () => {
    await userRepository.query(`DELETE FROM users;`)
})

describe('users/roles (GET)', () => {
    it('should retrieve all available roles', async () => {
        const { body } = await request(app.getHttpServer())
            .get('/users/roles')
            .set('accept', 'application/json')
            .expect('Content-Type', /json/)
            .expect(200)

        expect(body).toEqual(
            expect.arrayContaining([
                {
                    id: expect.any(String),
                    name: RoleName.STUDENT
                },
                {
                    id: expect.any(String),
                    name: RoleName.TEACHER
                },
                {
                    id: expect.any(String),
                    name: RoleName.ADMIN
                }
            ])
        )
    })
})

【问题讨论】:

    标签: javascript typescript testing jestjs nestjs


    【解决方案1】:

    目前的实现不可能立即实现,但如果你将守卫模拟保存为jest 模拟,它应该是可能的。像这样的

    describe('Controller Integration Testing', () => {
      let app: INestApplication;
      const canActivate = jest.fn(() => true);
    
      beforeEach(async () => {
        const moduleFixture: TestingModule = await Test.createTestingModule({
          imports: [AppModule],
        })
          .overrideGuard(TestGuard)
          .useValue({ canActivate })
          .compile();
    
        app = moduleFixture.createNestApplication();
        await app.init();
      });
    
      it('/ (GET)', () => {
        return request(app.getHttpServer())
          .get('/')
          .expect(200)
          .expect('Hello World!');
      });
      it('/ (GET) Fail guard', () => {
        canActivate.mockReturnValueOnce(false);
        return request(app.getHttpServer())
          .get('/')
          .expect(403);
      });
    });
    

    【讨论】:

    • 嗨,杰伊!非常感谢您的回复。它应该以这种方式工作!我认为这是最好的方法,否则我能想到的唯一可能性是创建几个“描述”并且每个都有自己的 TestModuleBuilder,但我认为这不是一个好主意。谢谢!
    猜你喜欢
    • 2023-03-15
    • 2020-05-03
    • 2019-09-14
    • 1970-01-01
    • 2020-08-27
    • 2020-05-29
    • 1970-01-01
    • 2022-08-11
    • 2019-10-06
    相关资源
    最近更新 更多