DEV Community

Cover image for Configurando testes de integração no Nestjs com o Typeorm
Yan.ts
Yan.ts

Posted on

6 1

Configurando testes de integração no Nestjs com o Typeorm

Teste de integração

Testes de integração como o nome já dá uma noção, são testes integrados com serviços externos, então por exemplo: em um teste unitário eu faço o mock do retorno do banco de dados para não precisar me conectar no banco de dados e fazer as queries. Enquanto nos testes de integração a ideia é subir um banco de dados separado só para teste e rodar e depois destruir esse banco.

Por que usar o teste de integração? tive essa necessidade principalmente pois os testes unitários não me deixaram confortável em garantir o pleno funcionamento da aplicação. Em alguns endpoints onde a função principal era fazer uma busca paginada por exemplo os testes unitários não bastavam pois o que mais importa nessa função é a querie que vai rodar no banco e as suas variações com filtros, e no teste unitário como eu que defino o retorno que a função vai ter não ia ter como testar isso.

Fazendo as configurações

Primeiro precisei configurar uma conexão 'mãe' que vai ser responsável por criar o banco de dados, e também configurar uma conexão secundaria que vai ser a conexão com o banco de testes

const masterConnection = new DataSource({
  type: 'postgres',

  database: process.env.DATABASE_NAME,
  host: process.env.DATABASE_HOST,
  password: process.env.DATABASE_PASSWORD,
  port: process.env.DATABASE_PORT
    ? parseInt(process.env.DATABASE_PORT, 10)
    : undefined,
  username: process.env.DATABASE_USERNAME,

  entities: ['dist/**/*.entity{.ts,.js}'],
  migrations: ['dist/src/db/migrations/*.js'],

  logging: false,
  name: 'master',
  migrationsRun: false,
});

const connection = new DataSource({
  ...(masterConnection.options as PostgresConnectionOptions),
  database: databaseName,
  migrationsRun: true,
  name: undefined,
});

Enter fullscreen mode Exit fullscreen mode

e então fiz uma função para fazer a conexão e criar o banco de dados o banco de dados e gerei um nome aleatório para o banco

Não é obrigatório gerar um nome aleatório pois ainda vou apagar o banco de testes quando acabar com teste poderia também ser um nome definido como 'test_db' por exemplo

Nessa função fazemos a conexão que vai gerar o banco, geramos ele e retornamos a conexão com esse banco gerado

const databaseName = `test_${randomBytes(8).toString('hex')}`;


export async function databaseIntegrationSetup() {
  try {
    await masterConnection.initialize();
    await masterConnection.query(`CREATE DATABASE "${databaseName}"`);
  } catch (err) {
    process.stderr.write(
      `${err instanceof Error ? err.stack : JSON.stringify(err)}\n`,
    );
    process.exit(1);
  }

  return connection;
}
Enter fullscreen mode Exit fullscreen mode

E uma função para fechar a conexão com o banco de dados, onde ele dropa o database criado para testes e fecha a conexão

export async function closeDatabaseIntegrationConnections() {
  try {
    await masterConnection.query(`DROP DATABASE "${databaseName}"`);
    await masterConnection.destroy();
  } catch (err) {
    process.stderr.write(
      `${err instanceof Error ? err.stack : JSON.stringify(err)}\n`,
    );
    process.exit(1);
  }
}
Enter fullscreen mode Exit fullscreen mode

Inicializando o teste

describe('Integrations tests', () => {
  let app: INestApplication;
  jest.setTimeout(30000);

  beforeAll(async () => {
    const databaseConnection = await databaseIntegrationSetup();

    const module: TestingModule = await Test.createTestingModule({
      imports: [TypeOrmModule.forRoot(databaseConnection.options)],
    }).compile();

    app = module.createNestApplication();

    await app.init();
  });

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

  it('should be defined', async () => {
    expect(app).toBeDefined();
  });
});
Enter fullscreen mode Exit fullscreen mode

Para definirmos o teste a gente basicamente vai pegar a conexão com o database que retornamos na primeira função e vamos declarar um modulo de testes e passar essa conexão para o modulo do Typeorm, e vamos inicializar o app nesse momento o teste já vai passar, porem depois de todos os testes rodarem precisamos fechar o app e chamar a função de fechar a conexão com o banco de dados e apagar esse banco criado só para testes

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay