Search code examples
typescriptjestjstypeormsupertest

TypeORM fails to find a connection when testing an Express app with Supertest


I'm building a TypeScript Node.js/Express application and started implementing some integration tests with Jest and Supertest, but even after setting up a TypeORM connection successfully my tests fail saying that a connection was not found.

This is what I currently have in my test file:

let conn: Connection;

describe('tests admin routes', () => {
  beforeAll(async () => {
    conn = await createConnection();
    registerDeps(); // registers dependencies on my tsyringe container
  });

  afterAll(async () => {
    await conn.close();
  });

  it('should be able to authenticate admins', async () => {
    const { status } = await supertest(app) // app is an `Express` "instance"
      .post('/admins/auth')
      .send({
        email: '[email protected]',
        password: 'mypassword',
      });

    console.log(status);
  });
});

If I run jest on my terminal, I get the following:

FAIL  src/modules/admin/web/controllers/__tests__/AdminsController.spec.ts
  ● Test suite failed to run

    ConnectionNotFoundError: Connection "default" was not found.

      at new ConnectionNotFoundError (src/error/ConnectionNotFoundError.ts:8:9)
      at ConnectionManager.Object.<anonymous>.ConnectionManager.get (src/connection/ConnectionManager.ts:40:19)
      at Object.getRepository (src/index.ts:284:35)
      at new VideosRepositoryTORM (src/modules/course/infrastructure/lib/typeorm/repositories/VideosRepositoryTORM.ts:11:26)
      at Object.<anonymous> (src/modules/course/web/controller/CoursesController.ts:12:26)
      at Object.<anonymous> (src/modules/course/web/routers/courses.router.ts:5:1)

Test Suites: 1 failed, 1 total
Tests:       0 total
Snapshots:   0 total
Time:        3.89 s
Ran all test suites.

I'm a bit confused because none of the services my controller calls uses that VideosRepositoryTORM and if I use that conn to resolve a repository, doing conn.getRepository(Admin) for example (Admin being a TypeORM entity) and then call any Repository method like find or query it actually returns data stored on the database, which leads me to believe that my connection was indeed established and is working.

Also, my application works fine when ran with node, it's just outputting this connection error on the tests. And it might be worth mentioning that I'm using tsyringe to inject repository implementations into my services, but I don't think it is causing the problem. Does anyone have an idea on what might be happening here?


Solution

  • What's happening here is I have two connections on my 'ormconfig.js' file:

    module.exports = [
      {
        name: 'default',
        type: 'postgres',
        // ...
      },
      {
        name: 'test',
        type: 'postgres',
        // ...
      },
    ];
    

    And, if not told otherwise, typeorm always tries to do stuff with the 'default' connection. For example, loading an Entity repository with getRepository(Teacher) is equivalent to getRepository(Teacher, 'default'). So typeorm is in fact creating the connections, but it's trying to use 'default' instead of 'test' when I run my integrations tests.

    There are a few things you can do to work around this when you're using multiple connections:

    1. Hardcoding which connection you want to use every time (which will not work well for most cases);

    2. Setting environment variables and using them to select which connection you want (which is the most flexible option);

    3. Loading the desired connection configuration and "renaming" it to 'default', or whatever other name you may use, when creating the connection.

    In my case I opted for the third option, so I've put the following in the tests:

    beforeAll(async () => {
        const connOpts = await getConnectionOptions('test');
        conn = await createConnection({ ...connOpts, name: 'default' });
        // ...
    });
    

    If you were to use more than two connections the second option would probably be better, but the third would also work. It's entirely up to you to decide.