Estoy tratando de escribir una prueba e2e con supertest donde mi controlador realmente usa el decorador @Session()
. Sin embargo, no quiero tener la carga completa de iniciar una sesión con conexión db y así sucesivamente, de modo que mi aplicación en la prueba no inicialice la sesión.
En cambio, me gustaría simular los datos proporcionados por Decorator en primer lugar y reemplazarlos con datos estáticos. Sin embargo, realmente no puedo encontrar una solución sobre cómo realizar esto.
Muestra del controlador:
@Get('/user/me') public async getMe(@Session() session: Record<string, unknown>) { if (!session?.user) { throw new InternalServerErrorException(); } return session.user; }
Lo que idealmente me gustaría que fuera el simulacro:
jest.mock(Session, jest.fn().mockImplementation(() => { return { user: { name: "test user" } }; })
sin embargo, esto no funcionará.
De acuerdo con la documentación oficial de TypeScript, los decoradores de parámetros solo se pueden usar para observar que un parámetro se ha establecido en un método particular. Como esto no es realmente lo que sucede cuando se usa el decorador @Session()
, intenté echar un vistazo al código fuente de cómo nestjs realmente implementa estos decoradores y tengo algunos problemas para entenderlo correctamente.
Si no me equivoco, parece que el decorador escribe algunos metadatos que otro decorador (¿probablemente @Get()
en este caso?) Puede usar y extraer los datos necesarios en función de eso.
Estoy un poco confundido sobre cómo probar esto correctamente, así que estaría muy agradecido por algún consejo :)
================================================== =========================
Actualización: ahora seguiré adelante y, en lugar de burlarme del decorador de sesiones, me burlaré de la sesión requerida mientras configuro mi app
en beforeAll()
. Por lo tanto, elegí la siguiente solución:
app.use((req, res, next) => { req.session = { user: { firstName: 'Max', lastName: 'Mustermann', }, }; next(); });
Todavía estaré muy feliz en caso de que alguien sepa una mejor solución.
Para resolver el problema, cree una función común que cree la aplicación nest para e2e y proporcione la configuración de ganchos que permite anular el módulo de prueba y la inyección de middleware de la aplicación de express
/** * Hook for overriding the testing module */ export type TestingModuleCreatePreHook = ( moduleBuilder: TestingModuleBuilder, ) => TestingModuleBuilder; /** * Hook for adding items to nest application */ export type TestingAppCreatePreHook = ( app: NestExpressApplication, ) => Promise<void>; /** * Sets basic e2e testing module of app */ export async function basicE2eSetup( config: { moduleBuilderHook?: TestingModuleCreatePreHook; appInitHook?: TestingAppCreatePreHook; } = {}, ): Promise<[NestExpressApplication, TestingModule]> { let moduleBuilder: TestingModuleBuilder = Test.createTestingModule({ imports: [AppModule], }); if (!!config.moduleBuilderHook) { moduleBuilder = config.moduleBuilderHook(moduleBuilder); } const moduleFixture: TestingModule = await moduleBuilder.compile(); const app = moduleFixture.createNestApplication<NestExpressApplication>(); if (config.appInitHook) { await config.appInitHook(app); } return [await app.init(), moduleFixture]; }
describe('AppController (e2e)', () => { let app: INestApplication; beforeEach(async () => { [app] = await basicE2eSetup({ moduleBuilderHook: (moduleBuilder) => { // your overrides go here // Refer: https://docs.nestjs.com/fundamentals/testing#end-to-end-testing // eg: moduleBuilder.overrideProvider(ProviderName).useValue(value) return moduleBuilder; }, appInitHook: async (app) => { const result = await someAction(); // or get some service from app // eg: const service = app.get<YourService>(YourService) app.use((req, res, next) => { // do something with request of response object next(); }) } }); }); it('/ (GET)', () => { return request(app.getHttpServer()) .get('/') .expect((res) => { expect(res.text).toContain('Hi There'); }); }); });