Um teste do caso de uso com um repositório em memória consegue provar que a aplicação recusa uma despesa inválida. Para provar que duas transações disputam a mesma restrição única, o teste precisa passar pelo PostgreSQL. É o banco que decide a ordem dos bloqueios e o resultado do conflito.
Suba um banco descartável e execute as migrações reais
Use um banco ou schema isolado para a suíte e rode as mesmas migrações da aplicação. Evite recriar tabelas à mão dentro do teste. Uma coluna ou restrição esquecida nesse schema paralelo permite que a suíte passe enquanto a aplicação falha após o deploy.
Para casos comuns de repositório, prepare os dados mínimos e confira tanto o retorno quanto o estado persistido. Se os testes rodam em paralelo, reserve escopos de dados independentes. Um rollback ao final ajuda apenas quando o código exercitado usa a mesma transação do teste. Uma requisição HTTP que abre sua própria conexão pode escapar desse isolamento.
Controle a ordem de eventos
Em um teste de idempotência, mantenha a primeira transação aberta depois de reservar a chave. Dispare a segunda tentativa por outra conexão e libere a primeira usando uma barreira explícita. A suíte deve ter timeout para evitar ficar presa se o código entrar em deadlock. Compare o número de linhas e os IDs devolvidos pelas duas operações.
Teste também a atualização a partir da versão anterior do schema quando a mudança transforma dados existentes. Criar um banco vazio cobre a instalação inicial. Atualizar um banco com registros antigos cobre o caminho que a produção vai percorrer.
Pacote testing da biblioteca padrão de Go · Idempotência com PostgreSQL