envalid icon indicating copy to clipboard operation
envalid copied to clipboard

different defaults for test and development

Open misha-erm opened this issue 4 years ago • 5 comments

Hi, bringing up the similar question to #32

The problem I'm trying to solve is to use different URI for mongo in tests because I'm dropping the entire collection after each test.

So what I want to achieve is something like that:

ENV_MONGO_URI: str({ devDefault: 'mongodb://mongo:27017/app', testDefault: 'mongodb://mongo:27017/app-test' })

If I understand correctly I can't use testOnly for that case since in development my uri will be undefined.

Thanks in advance!

misha-erm avatar Nov 06 '20 10:11 misha-erm

That's correct, testOnly('foo') will only use 'foo' as a default value when NODE_ENV is test. Since you probably can control your test environment, why not just add ENV_MONGO_URI=... as part of your testing command?

af avatar Nov 22 '20 23:11 af

Yes, that's an option. But then I don't understand why we need devDefault since we can control dev environment too.

Currently I use a helper similar to testOnly, but it accepts two values: one for test and one for dev as a fallback. Maybe this version of testOnly where you can specify a fallback would be a bit more comfortable? What do you think?

misha-erm avatar Nov 23 '20 11:11 misha-erm

I second request for testOnly. Since NODE_ENV=test is first-class citizen (there's isTest), I think it worth having ability to have different defaults for dev & test will make things more consistent. Things behave somewhat different for "dev" (real service start for local development or staging environments) and "test" (run automated tests, units and integration, does not launch some global components). Simplest practical usecase is e.g logging, which is supressed by default in test, but not in dev.

 cleanEnv(
    inputEnv,
    {
      LOG_LEVEL: str<LevelWithSilent>({
        default: 'info',
        testDefault: 'silent',
        choices: ['fatal', 'error', 'warn', 'info', 'debug', 'trace', 'silent'],
      }),
   }
);

I can take time to implement that if necessary.

meredian avatar Nov 18 '22 08:11 meredian

 if (rawValue === undefined) {
            // Use devDefault values only if NODE_ENV was explicitly set, and isn't 'production'
            var usingDevDefault = rawNodeEnv && rawNodeEnv !== 'production' && spec.hasOwnProperty('devDefault');

it's because of this condition in getSanitizedEnv

DenisVASI9 avatar Dec 12 '23 20:12 DenisVASI9

I end up just using class-transformer because I already have it in my nestjs project

 @Expose()
 @IsString()
 @Transform(({ value }) => process.env.NODE_ENV === 'test' ? 'postgresql://testuser:testpassword@localhost:7000/testdb' : value)
 DATABASE_URL!: string;
function loadConfig() {
const config = plainToInstance(EnvironmentConfig, process.env, { enableImplicitConversion: true, strategy: 'excludeAll' });
const errors = validateSync(config, { skipMissingProperties: false });

if (errors.length > 0) {
  throw new Error(`Configuration validation error: ${errors}`);
}

return config;
}

export const ENV = loadConfig();

DenisVASI9 avatar Dec 12 '23 21:12 DenisVASI9