No último final de semana, eu passei praticamente a tarde toda do domingo tentando escrever testes unitários para o GORM utilizando sqlmock.
O problema é que todos os tutoriais que eu encontrei eram de versões antigas, tanto do GORM, quanto do sqlmock.
Somente na segunda-feira, depois de mais umas 2h tentando entender como eles funcionavam e o que os erros estavam me dizendo foi que consegui fazer os testes funcionarem.
Por causa desse trabalho todo, resolvi fazer esse post mostrando como escrever testes unitários para GORM com sqlmock e testify.
Se você nunca utilizou testify ou quer saber um pouco mais sobre, recomendo a leitura do nosso post “Como usar testify para escrever testes“. Além de um exemplo básico, explicamos qual a finalidade de cada um dos 4 packages que compõem a suite do testify.
Continuando… para facilitar, vou separar o post em testes para INSERT, UPDATE, DELETE e SELECT.
Antes de começar a escrever os testes, vamos criar um arquivo person.go com uma struct, um repository e uma função para fazer migration e retornar uma nova instância do repository.
No arquivo de testes, o person_test.go, vamos precisar de uma suite de testes do testify. Para isso, precisamos criar uma struct e um método SetupSuite.
Se você prestar atenção, vai ver que o import desse arquivo tem mais packages do que usamos até agora. Não se preocupe, todos esses packages serão usados ao longo da implementação dos testes. Preferi adicioná-los logo no começo para que possamos focar na escrita dos testes.
Por último, antes de iniciar, vamos adicionar mais um método à nossa suite de testes.
Esse método irá checar após cada teste se todas as expectativas foram atendidas corretamente.
Insert
Para o insert, vamos considerar o seguinte método.
Como ao executar o método Create
o GORM executa uma transação, para escrever nosso teste precisamos seguir os seguintes passo:
- Iniciar uma transação
- Executar a transação
- Avaliar o retorno
- Commitar a transação
Se você olhar na documentação do sqlmock
verá que a função NewResult
espera os parâmetros ID e número de linhas afetadas.
Como ambos os parâmetros são do tipo int e nosso id é um UUID, não conseguimos passar o UUID como parâmetro. No entanto, utilizando o valor 1 como ID ele funciona corretamente.
Update
No repository, vamos adicionar o seguinte método.
Assim como o método Create
, o método Updates
também realiza uma transação com o banco de dados. Sendo assim, os passos necessários para testá-lo são praticamente os mesmos do insert.
Um ponto que vale a pena salientar aqui é que você não consegue mudar a order dos parâmetros na query. Em outras palavras, escrever a query assim UPDATE "people" SET "name"=$2 WHERE "id" = $1
não funciona.
Delete
Voltando para o nosso repository, vamos implementar o método Delete
.
E adivinha?!?!?! O método Delete
também realiza uma transação com o banco de dados com a função Exec
do package database/sql!
E como já conhecemos bem a ordem lógica, bora para o person_test.go implementar esse teste.
Note que diferente do update, o where no delete precisa ter o nome da tabela antes do nome do campo.
Select
Para o select, vamos implementar dois métodos. O primeiro será para buscar todos os registros, enquanto o segundo irá filtrar os registros pelo ID.
Para testar uma função do tipo select, vamos precisar mudar um pouco a sequência lógica que utilizamos até aqui.
Pelo fato dos select ser implementado em cima da função Query
do package database/sql os passos serão o seguintes:
- Adicionar uma lista de registros
- Adicionar a query que esperamos ser gerada
- Validar os registros retornados
Para filtrar um registro, só precisamos mudar a query que esperamos e adicionar os argumentos para realizar o filtro.
Calma que ainda não acabou!!!!
Se você tentar executar os testes agora, verá que nada irá acontecer. Isso por que não implementamos nenhuma função de teste do Go, tudo que fizemos até agora foi configurar a suite de testes do testify.
Para que essa suite de testes seja executada, precisamos adicionar a seguinte função.
Agora sim!!!! Se você executar um go test ./...
verá que todos os testes irão passar.
Deixem suas dúvidas nos comentários.
Até a próxima!