Popular banco de dados MySQL para testes de integração.
Matheus Viana
Posted on May 3, 2020
Hey,
Escrevo esse artigo para ajudar os outros devs que passaram por uma situação parecida com a que tive no projeto que estou atuando. Dockerizamos todos os nossos testes tanto os de unidade quanto os de integração (Sistêmicos), porém para realizarmos os testes de integração era necessário criarmos e popularmos o banco de dados, pesquisamos em vários fóruns e de todas as formas possiveis e nada foi encontrado, então resolvi fazer uma POC que solucionou nossos problemas e nela foi utilizado:
Antes de começarmos uns pontos a se atentar:
- Tinha um arquivo com todas as Queries SQL para criação do banco e das tabelas, um inserindo dados mockados e outro para derrubar todas as tabelas.
Script em Javascript usando o Package MySQL
const mysql = require('mysql');
const fs = require('fs');
// Aqui usei uma IIFE e uma função anonima, para nenhum metodo desse arquivo seja usado fora dele
(async function() {
try {
// Aqui realizamos a conexão com o banco de dados MySQL
const mysqlConn = await mysql.createConnection({
host: process.env.MYSQL_HOSTNAME,
port: process.env.MYSQL_PORT,
user: process.env.MYSQL_USER,
password: process.env.MYSQL_PASSWORD,
database: process.env.MYSQL_DATABASE,
// Como os arquivos com as queries tinham várias declarações eu settei para true o mesmo
multipleStatements: true,
});
// Aqui connecto com mysql
await mysqlConn.connect();
// Esse primeiro método ele cria o banco de dados caso não exista e cria as tabelas do banco
const createTablesNDB = async () => {
try {
const tablesNDB = fs.readFileSync(`${__dirname}/database.sql`, 'utf8');
await mysqlConn.query({ sql: tablesNDB.toString() });
// Aqui settei um timeout por algum motivo o script estava pulando para o process.exit()
setTimeout(() => {
process.exit();
}, 1500);
} catch (err) {
console.log(err);
}
};
// Nesse método é inserido os dados mockados nas tabelas criadas
const inserirDados = async () => {
try {
const data = fs.readFileSync(`${__dirname}/_data.sql`, 'utf8');
await mysqlConn.query({ sql: data.toString() });
setTimeout(() => {
process.exit();
}, 1500);
} catch (err) {
console.log(err);
}
};
// Nesse outro método é dropado todas as tabelas para não haver conflitos de FK, ao rodar o banco novamente e toda vez que forem executados os testes recriar o banco e as tabelas, para não viciarmos nossos testes
const removerTabelas = async () => {
try {
const dropTables = fs.readFileSync(
`${__dirname}/_drop.sql`,
'utf8',
);
await mysqlConn.query({ sql: dropTables.toString() });
setTimeout(() => {
process.exit();
}, 1500);
} catch (err) {
console.log(err);
}
};
// Aqui criamos uma CLI simples onde possui 3 subcomandos
// O process.argv ele é um array com os argumentos passados em um comando que no caso nosso comando seria $ node db.js --[create || insert || drop]
if (process.argv[2] === '--create') {
criarTabelaseBD();
} else if (process.argv[2] === '--insert') {
inserirDados();
} else if (process.argv[2] === '--drop') {
removerTabelas();
}
} catch (err) {
// Aqui logamos todos os erros
console.error('ERROR >>>>>>>>>>>', err, 'MESSAGE >>>>>', err.message);
}
})();
Com esse arquivo você pode criar um arquivo .sh
e passar a ordem dos comandos, exemplo:
#!/bin/bash
npm test &&
node ./db.js --drop &&
node ./db.js --create &&
node ./db.js --insert &&
npm run test:integration &&
node ./db.js --drop
No seu Dockerfile de testes na linha de CMD
você pode rodar ["sh", "./tests.sh"]
que o Docker fará toda mágica para você hehe, não esqueçam de settar o env-file
caso estiver usando docker-compose
e também de settar as variáveis de ambiente no seu arquivo de environment.
E é isso pessoal, adendo esse código é uma proof of concepts.
Qualquer dúvida é só deixar nos comentários que eu responderei.
LinkedIn: https://www.linkedin.com/in/matheusviana/
GitHub: https://github.com/moviandev
Até a próxima meus camaradas.
Posted on May 3, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.