Quando o teste está em execução, as @Transactional
anotações na classe de teste farão com que Entity
a operação dos dados no teste seja concluída na memória e, eventualmente, a commit
operação não será executada, ou seja, os Entity
dados não serão persistidos, resultando no comportamento e na aplicação real do teste. O comportamento de S é inconsistente.
O gerenciamento de transações é um design indispensável no desenvolvimento de aplicativos e é um padrão para o processamento de persistência do banco de dados. Sabemos que o desenvolvimento de aplicativos é inseparável dos dados CRUD
(adição, exclusão, modificação e inspeção), e a ACID
natureza da transação pode garantir melhor a integridade dos dados e dos dados relacionados 同生共死
. O ciclo de vida de uma única transação é dividido principalmente em três estágios, BEGIN TRANSACTION
-> COMMIT TRANSACTION
-> ROLLBACK TRANSACTION
.
Spring Boot
O uso de transações é dividido em imperativo e declarativo, e a maneira comum é a anotação declarativa ( @Transactional
). O gerenciamento de transações pode ser usado na camada de aplicativos e nos testes.
Para garantir a independência entre os testes, os dados entre os testes não serão afetados um pelo outro. Talvez você tenha escrito um teste como este:
@SpringBootTest
@ActiveProfiles("test")
@Transactional
public class UserControllerTest { }
@Transactional
Ao truncar a operação de persistência de dados, é resolvido o problema de que os testes se opõem e os dados não se afetam. No entanto, esse método tem efeitos colaterais , ou seja, o processo de persistência de dados não é mais verdadeiro e o processo se foi commit
. Isso leva a:
- Não há garantia
Entity
da relação entre a associação, a precisão da associação entre o índice exclusivo e a chave estrangeira primária- Não é possível garantir a precisão do
Entity
tempo de criação, do tempo de atualização e da lógica de atribuição com versão (bloqueio otimista)- Nós não podemos garantir que
Entity
não há@Transient
uma atribuição de precisão atributo anotação lógica- Os dados do teste não são um problema na cena real
- No teste, os dados preparados em uma única transação não podem ser compartilhados entre vários encadeamentos.
......
Então, qual é a intenção original de Spring
introduzir o gerenciamento de transações no domínio do problema de teste ? Para resolver que problema é necessário apresentá-lo? O documento oficial apresenta o gerenciamento de transações
De acordo com a documentação oficial, para resolver a execução do teste, o programa acessa o banco de dados real e altera o estado dos dados, o que afeta os problemas subsequentes do teste.
De fato, aqui deve haver um pensamento crítico , por que você precisa acessar o banco de dados real quando o teste é executado? Por que os dados entre os testes se afetam?
Para cada teste, deve haver um contexto limpo antes de cada execução, ou um contexto independente, existe um processo de limpeza e preparação de dados e os testes são isolados um do outro. Ou seja, por que o teste não pode usar banco de dados na memória ou banco de dados incorporado? Por que não limpar os dados no banco de dados antes de cada execução de teste para garantir que a terra pura antes da execução do caso de teste não seja afetada pelos dados de teste anteriores?
A resposta é, claro ! ! !
Escreva no final
Como fazer isso? Implemente um TruncateDatabaseService
, exclua apenas os dados da tabela, não exclua o resultado da tabela. Na classe base de teste @BeforeEach
, execute truncate
. Banco de dados truncado de origem :