雀巢 | 端到端测试 | 在 ConfigModule 触发验证之前“走私/注入”自定义环境变量

fma*_*gno 5 node.js typescript nestjs

如何在envValidation发生这种情况之前将自己的测试环境变量“走私”到 ConfigModule/ConfigService 中?这对于检查以下内容很有用:

  • 该功能envValidation正在正确执行其工作;
  • 下游,应用程序根据设置的变量运行。
// AppModule.ts


import { validate as envValidate } from './configs/EnvValidation';


@Module({
    imports: [
        TypeOrmModule.forRootAsync({
            imports: [ConfigModule],
            useFactory: (configService: ConfigService) => ({
                type: configService.get('DATABASE_TYPE'),
                host: configService.get('DATABASE_HOST'),
                port: configService.get<number>('DATABASE_PORT'),
                username: configService.get('DATABASE_USERNAME'),
                password: configService.get('DATABASE_PASSWORD'),
                database: configService.get('DATABASE_NAME'),
                entities: [EntityA, EntityB],
                entityPrefix: "simple_auth_",
                synchronize: true,
            }  as ConnectionOptions),
            inject: [ConfigService],
        }),
        TypeOrmModule.forFeature([EntityA, EntityB]),
        ConfigModule.forRoot({
            cache: true,
            validate: envValidate
        })
    ],
    controllers: [
        // controllers...
    ],
    providers: [
        // providers...
    ],
})
export class AppModule {}
Run Code Online (Sandbox Code Playgroud)
// EnvValidation.ts


class EnvironmentVariables {
    @IsIn(['mysql', 'postgres'])
    @IsDefined()
    @IsNotEmpty()
    DATABASE_TYPE: string;

    @IsDefined()
    @IsNotEmpty()
    DATABASE_HOST: string;

    @IsPort()
    @IsDefined()
    @IsNotEmpty()
    DATABASE_PORT: string;

// (...)
}


export function validate(config: Record<string, unknown>) {
    const validatedConfig = plainToClass(EnvironmentVariables, config, {
        enableImplicitConversion: true
    });
    const errors = validateSync(validatedConfig, {
        skipMissingProperties: false
    });

    if (errors.length > 0) {
        const msgs = errors.map((err) => Object.values(err.constraints)[0]);
        const errorMsg = msgs.join(', ');

        throw new Error(`Error loading environment variables. ${errorMsg}`);
    }

    return validatedConfig;
}
Run Code Online (Sandbox Code Playgroud)
// e2e-spec.ts



describe('(e2e)', () => {
    beforeEach(async () => {});

    afterEach(async () => {});

    it('should pass while setting: DATABASE_TYPE=postgres, DATABASE_HOST=localhost, ...', async () => {

        const envVariablesToUse = {
            DATABASE_TYPE: 'postgres',
            DATABASE_HOST: 'localhost',
            // more variables for this test...
        }

        const moduleFixture: TestingModule = await Test.createTestingModule({
            imports: [
                AppModule,
                // ??
            ]
        })
            .overrideModule(ConfigModule)
            .useValue(ConfigModule.forRoot({envVars: envVariablesToUse}))  // <-- Question 1: How to override the environment variables object with a custom one in order to test the rules defined in the EnvironmentVariables class and to test the implications of these configurations downstream?

            .overrideProvider(ConfigService) // <-- Question 2: How to override the ConfigService? May be handy to replace its behaviour(?)
            .useValue(MockConfigService)
            .compile();

        const app = moduleFixture.createNestApplication();

        let successfullyLoadedEnvVariables = true;
        try {
            await app.init();
        }
        catch(err){
            successfullyLoadedEnvVariables = false;
        }

        expect(successfullyLoadedEnvVariables).toBe(true);

        // Then, hit some endpoints to ensure the app is behaving as expected
    });
});
Run Code Online (Sandbox Code Playgroud)

stackoverflow padding:看起来你的帖子主要是代码;请添加更多详细信息。
stackoverflow padding:看起来你的帖子主要是代码;请添加更多详细信息。

fma*_*gno 5

我找到的解决方案是将AppModule转换为动态模块,并通过.register()方法中的process.env设置环境变量。