0

I would like to create a new environment for testing my app. I have a .env file and .env.test file.

This is my app.module.ts file:

@Module({
  imports: [
    ConfigModule.forRoot({
      envFilePath: !process.env.NODE_ENV
        ? '.env'
        : `.env.${process.env.NODE_ENV}`,
    }),
    TypeOrmModule.forRoot({
      type: 'postgres',
      host: process.env.POSTGRES_HOST,
      port: parseInt(<string>process.env.POSTGRES_PORT),
      username: process.env.POSTGRES_USER,
      password: process.env.POSTGRES_PASSWORD,
      database: process.env.POSTGRES_DATABASE,
      autoLoadEntities: true,
      entities: [User],
      synchronize: true,
    }),
    AuthModule,
  ],
  controllers: [],
  providers: [],
})
export class AppModule {}

The problem here is that .env.test is never called, .env always runs even though process.env.NODE_ENV returns test. And this is how i set up my package.json file:

 "start:test": "NODE_ENV=test nest start --watch",

This is how my .env.test file looks like

POSTGRES_HOST=localhost
POSTGRES_PORT=5432
POSTGRES_USER=postgres
POSTGRES_PASSWORD=Random
POSTGRES_DATABASE=db-test

I also tried to hardcode envFilePath: '.env.test', and it still not working. For .env.test file to work i have to rename .env file and then it works fine.

UPDATE!

It works now. What i did was i put

ConfigModule.forRoot({
      envFilePath: !process.env.NODE_ENV
        ? '.env'
        : `.env.${process.env.NODE_ENV}`,
    }),

in every module i have in my app.

Krneki123
  • 67
  • 5
  • How do you know that `.env.test` is not read? – Jay McDoniel Apr 27 '22 at 16:09
  • because tables are not created in test database. – Krneki123 Apr 27 '22 at 16:09
  • But you're using `process.env` directly instead of using the `ConfigService` from `@nestjs/config`, right? So how do _you_ populate `process.env` with the values from `.env.test` – Jay McDoniel Apr 27 '22 at 16:12
  • I updated my post so it includes what i have in my `.env.test` file, if that is what you meant. But i will look into `ConfigService`. – Krneki123 Apr 27 '22 at 16:17
  • Make sure you don't have these variables defined at the OS level — they take precedence over those specified in the `.env` file. Another issue might be that the Nest CLI does not allow you to override the `NODE_ENV` variable, you could try a different name. Otherwise your setup works and is in fact something I'm using as well. – skink Apr 27 '22 at 16:41
  • My `.env` and `.env.test` are defined at the root of the project. By different name you mean something like `NODE_ENV_V` and i change to this new name in `package.json` file and in `app.module.ts` file. – Krneki123 Apr 27 '22 at 17:04

1 Answers1

0

As you're using the ConfigModule presumably from @nestjs/config you should be using the TypeormModule's forRootAsync method to make sure you use the read .env file.

@Module({
  imports: [
    ConfigModule.forRoot({
      envFilePath: !process.env.NODE_ENV
        ? '.env'
        : `.env.${process.env.NODE_ENV}`,
    }),
    TypeOrmModule.forRootAsync({
      inject: [ConfigService],
      useFactory: (config: ConfigService): PostgresConnectionOptions => ({
        type: 'postgres' as const,
        host: config.get('POSTGRES_HOST'),
        port: parseInt(config.get('POSTGRES_PORT')),
        username: config.get('POSTGRES_USER'),
        password: config.get('POSTGRES_PASSWORD'),
        database: config.get('POSTGRES_DATABASE'),
        autoLoadEntities: true,
        entities: [User],
        synchronize: true,
      }),
    }),
    AuthModule,
  ],
  controllers: [],
  providers: [],
})
export class AppModule {}
Jay McDoniel
  • 57,339
  • 7
  • 135
  • 147
  • Thanks i think this is the right way to do it, but i get this long error in `useFactory`. – Krneki123 Apr 27 '22 at 16:41
  • Can you add the error to a pastebin or similar? It's probably something like a missed type on my part – Jay McDoniel Apr 27 '22 at 16:45
  • Here it is: https://pastebin.com/kJmSi0eN – Krneki123 Apr 27 '22 at 16:48
  • The `.env` file is guaranteed to be loaded into `process.env` after the `ConfigModule.forRoot()` call in this setup. Both `dotenv` and `dotenv-expand` are synchronous and the latter modifies `process.env`. This asynchronous trickery is not necessary. – skink Apr 27 '22 at 16:53
  • @Joulukuusi but nothing guarantees that `ConfigModule.forRoot()` (and the subsequent configuration called by `ConfigService`'s `constructor` is called _before_ `TypeormModule.forRoot()` is called. This is why we, the Nest team, encourage the use of `forRootAsync` and the dependency on the `ConfigService` in a factory – Jay McDoniel Apr 27 '22 at 17:11
  • @Krneki123 the `type: 'postgres' as const` should have ensured that the `PostgresConnectionOptions` type was used, but for some reason it wasn't, I've added the type assertion for the `useFactory` return type, if that doesn't fix it then add `as PostgresConnectionOptions` at the end of the factory return. Strange that Typescript is bugging out on this – Jay McDoniel Apr 27 '22 at 17:17
  • Thanks for your help but its not generating tables in database. What is also strange is if i hardcode `envFilePath: '.env.test',` it still not working. It only works if i rename `.env` to something else then `.env.test` generates tables in my test database. – Krneki123 Apr 27 '22 at 17:35
  • That seems very strange. If you could provide access to your repo I'd like to take a look – Jay McDoniel Apr 27 '22 at 17:38
  • Sorry i can't share my repo. But i quickly created a new nest app and i did everything like i have in my original post and it worked. So i now i have to find why is it not working in my project. But thanks for your help! – Krneki123 Apr 27 '22 at 18:10