TypeORM with multiple env setups

Viewed 10270

I want to use a separate database for running tests. So I tried to configure TypeORM for multiple environments (dev and test) but it's not working. It only use the 'dev' configuration.

This is my npm scripts:

"scripts": {
    "start": "NODE_ENV=dev node dist/index.js",
    "test": "NODE_ENV=test mocha --reporter spec --compilers ts:ts-node/register 'test/**/*.test.ts'"
}

If I console.log(process.env.NODE_ENV) I get the correct results ("dev" / "test").

This is my ormconfig.json

[
  {
    "environment": "dev",
    "name": "default",
    "driver": {
      "type": "mysql",
      "host": "localhost",
      "port": 3306,
      "username": "root",
      "password": "",
      "database": "api"
    },
    "entities": [ "dist/model/*.js" ],
    "autoSchemaSync": true
  },
  {
    "environment": "test",
    "name": "default",
    "driver": {
      "type": "mysql",
      "host": "localhost",
      "port": 3306,
      "username": "root",
      "password": "",
      "database": "api_test"
    },
    "entities": [ "dist/model/*.js" ],
    "autoSchemaSync": true
  }
]

I connect with createConnection();. I manually created both databases api and api_test beforehand.

Why is TypeORM not using the "test" configuration when I set NODE_ENV=test?

3 Answers

You could change your ormconfig.json to a js file then do something similar to this:

require('dotenv/config');


const database = {
  development: "dev-db",
  production: 'prod-db',
  test: 'test-db'
}

module.exports = {
  type: 'postgres',
  host: 'localhost',
  port: 5432,
  username: 'ur-username',
  password: 'password',
  database: database[process.env.NODE_ENV],
  entities: ['dist/**/*.entity{.ts,.js}'],
  synchronize: true,
  migrationsTableName: 'migration',
  migrations: ['migration/*.js'],
  cli: {
    migrationsDir: 'migration',
  },
};

Then when running your tests, don't forget to set the appropriate environment. NODE_ENV=test should do.

I had a similar problem. I got this to work by using different 'name' fields for each connection. For my run-time connection, I kept name=default, and for my test connection I used name=test. So:

[
  {
    "environment": "dev",
    "name": "default",
    "driver": {
      "type": "mysql",
      "host": "localhost",
      "port": 3306,
      "username": "root",
      "password": "",
      "database": "api"
    },
    "entities": [ "dist/model/*.js" ],
    "autoSchemaSync": true
  },
  {
    "environment": "test",
    "name": "test",          //// CHANGED
    "driver": {
      "type": "mysql",
      "host": "localhost",
      "port": 3306,
      "username": "root",
      "password": "",
      "database": "api_test"
    },
    "entities": [ "dist/model/*.js" ],
    "autoSchemaSync": true
  }
]

In my application, I would simply use createConnection(), which would automatically use the connection with name=default.

For my tests, I used typeorm's createConnections() (notice the s). This loads all connections. Once loaded, I would immediately after use getConnection('test'), which would get the test connection. My beforeAll in my tests looked like this in typescript:

  beforeAll(async () => {
    await createConnections();
    getConnection('test');
  });

In javascript, it would probably look something like:

  beforeAll(() => {
    createConnections().then(() => {
        getConnection('test');
    });
  });

Then my tests started to pass. Hope that helps.

This option is no longer available.

You can see the pull request that removed it from the TypeORM docs, in Aug, 2017, here: https://github.com/typeorm/typeorm.github.io/pull/13/files

The functionality itself seems to have been removed in a commit with other changes to fix another (unrelated?) issue. It is not immediately clear what the intent was in removing it.

Related