简体   繁体   English

Controller 使用不同的守卫与 nestJS 进行集成测试

[英]Controller integration testing with nestJS using different guards

I am trying to develop an application using NestJs as the backend framework.我正在尝试使用 NestJs 作为后端框架开发一个应用程序。 Currently I am writing some integration tests for the controllers.目前我正在为控制器编写一些集成测试。

This is my first project using typescript, I usually use Java/Spring but I wanted to learn and give nestJs a try.这是我使用 typescript 的第一个项目,我通常使用 Java/Spring,但我想学习并尝试 nestJs。

I use different guards to access rest endpoints.我使用不同的守卫来访问 rest 端点。 In this case I have an AuthGuard and RolesGuard在这种情况下,我有一个AuthGuardRolesGuard

To make the rest endpoint work I just add something like this in the TestingModuleBuilder:为了使 rest 端点正常工作,我只需在 TestingModuleBuilder 中添加如下内容:

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

The point is, is it possible to define or override this guards for each test to check that the request should fail if no guard or not allowed guard is defined?关键是,是否可以为每个测试定义或覆盖此守卫,以检查如果没有定义守卫或不允许守卫,请求是否应该失败?

My code for the test is the following one:我的测试代码如下:

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
                }
            ])
        )
    })
})

It's not immediately possibly with the current implementation, but if you save the guard mock as a jest mock it should be possible.当前的实现不可能立即实现,但是如果您将守卫模拟保存为jest模拟,它应该是可能的。 Something like this像这样的东西

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);
  });
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM