3
respostas

Banco próprio para testes

Esse curso poderia mostrar como separar um banco de dados só pra teste, enquanto temos outro banco para desenvolvimento. Como fazer isso?

3 respostas

Olá, Luidi! Joia?

Essa é uma prática comum e recomendada para evitar que dados de teste interfiram no ambiente de desenvolvimento ou produção. Vou te explicar como você pode fazer isso.

  1. Configuração de bancos de dados separados: a primeira coisa que você precisa fazer é configurar dois bancos de dados diferentes. Um será usado para desenvolvimento e o outro para testes. Isso pode ser feito criando dois arquivos de configuração, por exemplo, config.development.js e config.test.js, cada um apontando para o respectivo banco de dados.

  2. Utilização de variáveis de ambiente: uma prática comum é utilizar variáveis de ambiente para definir qual banco de dados deve ser usado. Por exemplo, você pode ter uma variável NODE_ENV que determina se o ambiente é de desenvolvimento ou de teste. Com isso, seu código pode carregar a configuração correta com base no valor dessa variável.

  3. Exemplo prático:

    • No seu arquivo de configuração principal, você pode ter algo como:
      const config = {
        development: {
          client: 'sqlite3',
          connection: {
            filename: './dev.sqlite3'
          }
        },
        test: {
          client: 'sqlite3',
          connection: {
            filename: './test.sqlite3'
          }
        }
      };
      
      module.exports = config[process.env.NODE_ENV || 'development'];
      
    • No seu script de teste, você pode definir a variável de ambiente antes de executar os testes:
      NODE_ENV=test npm run test
      
  4. Uso de bibliotecas de teste: algumas bibliotecas de teste, como o Jest, permitem configurar scripts de setup e teardown, que podem ser usados para criar e limpar o banco de dados de teste antes e depois de cada execução de teste.

Ao seguir essas etapas, você conseguirá manter seus ambientes de desenvolvimento e teste separados, garantindo que os dados de teste não interfiram no seu trabalho de desenvolvimento.

Espero ter ajudado e bons estudos!

Caso este post tenha lhe ajudado, por favor, marcar como solucionado ✓.

Esse teste abaixo é um teste de integração. Embora alguns chamam o fluxo completo de E2E, tecnicamente ele ainda é de integração porque estamos isolados no ecossistema do back-end.

describe('Testando a rota login (POST)', () => {
  it('O login deve possuir um email e senha para se autenticar', async () => {
    const loginMock = {
      email: 'raphael@teste.com.br',
    };

    await request(servidor)
      .post('/login')
      .send(loginMock)
      .expect(500)
      .expect('"A senha de usuario é obrigatório."');
  });

O teste abaixo é chamado de Teste de Integração focado em persistência (muitas vezes chamado apenas de teste de banco de dados).

describe('Testando configDB', () => {
  it('Teste de conexão com o banco de dados', async () => {
    const autorMock = {
      nome: 'Luana',
      nacionalidade: 'Brasileira',
      created_at: new Date().toISOString(),
      updated_at: new Date().toISOString(),
    };

    const autorSalvo = await db('autores').insert(autorMock)
      .then((retorno) => db('autores')
        .where('id', retorno[0]))
      .then((autorSelecionado) => autorSelecionado[0]);

      expect(autorSalvo.nome).toBe(autorMock.nome);

      await db('autores').where({ id: autorSalvo.id }).del();
  });
});

A minha dúvida é se eu crio um banco de teste para esses 2 testes ou teria que criar um banco de testes chamdo E2E para o primeiro teste, pois alguns o chamam assim apesar de não estar tecnicamente correto. Pois já vi dizer q para os testes E2E cria um banco separado, mas daí seria o E2E verdadeiro e não esse q alguns chamam assim?

Oi, Luidi!

Use o mesmo banco de testes para os dois cenários (rota /login com supertest e teste direto no db). O nome “E2E” não muda a estratégia de banco neste ponto: o que manda é isolar do banco de desenvolvimento e garantir previsibilidade nos testes. Resolva fazendo o seguinte, direto ao ponto:

  1. Crie um banco exclusivo de teste (ex.: ./database/test.sqlite3 ou um schema/DB separado no Postgres/MySQL).
  2. Selecione a configuração pelo NODE_ENV=test e sempre aponte para o banco de testes quando rodar os testes.
  3. Rode migrations no banco de teste antes dos testes e limpe as tabelas entre os testes (ou use transaction rollback, se fizer sentido no seu stack).

Ajuste seu código assim (Knex + SQLite, no mesmo estilo do curso):

// knexfile.js
module.exports = {
  development: {
    client: 'sqlite3',
    connection: { filename: './database/dev.sqlite3' },
    useNullAsDefault: true,
    migrations: { directory: './database/migrations' },
  },
  test: {
    client: 'sqlite3',
    connection: { filename: './database/test.sqlite3' },
    useNullAsDefault: true,
    migrations: { directory: './database/migrations' },
  },
};
// src/database/index.js
const knex = require('knex');
const knexfile = require('../../knexfile');

const env = process.env.NODE_ENV || 'development';
const db = knex(knexfile[env]);

module.exports = db;

No package.json, rode testes sempre com NODE_ENV=test:

{
  "scripts": {
    "test": "NODE_ENV=test jest --runInBand"
  }
}

E garanta migrations + limpeza no ciclo de testes. Um jeito objetivo com Jest:

// test/setup.js
const db = require('../src/database');

beforeAll(async () => {
  await db.migrate.latest(); // aplica migrations no banco de teste
});

beforeEach(async () => {
  // limpe as tabelas que seus testes usam (ordem importa por FK)
  await db('autores').del();
  await db('usuarios').del();
});

afterAll(async () => {
  await db.destroy();
});
// jest.config.js
module.exports = {
  setupFilesAfterEnv: ['<rootDir>/test/setup.js'],
  testEnvironment: 'node',
};

Com isso:

  • Seu teste da rota /login (fluxo HTTP) e seu teste direto no db (persistência) ficam isolados no mesmo banco de teste.
  • Você não precisa criar “um banco E2E” separado só por causa do nome do teste — isso só faria sentido se você tivesse outro ambiente realmente end-to-end (ex.: front + back + serviços externos) com outro tipo de setup.

Fico à disposição.