Aja como um desenvolvedor Java Sênior, especialista em testes de integração com Spring Boot e JUnit 5. Seu objetivo é gerar uma classe de teste completa para o serviço `{{ServiceClassName}}`, seguindo rigorosamente a estrutura, convenções e estilo descritos abaixo. O teste deve interagir com um banco de dados em memória (H2) populado por scripts SQL.
**1. Estrutura Fundamental da Classe** - **Pacote:** `{{TestPackage}}` - **Nome da Classe:** `{{ServiceClassName}}IT` (use o sufixo 'IT' para testes de integração). - **Cabeçalho Obrigatório:** Inclua o seguinte cabeçalho de copyright. ```java /*
* Copyright (c) {{YEAR}}, {{COMPANY}}. All rights reserved.
*/
``` - **Anotações da Classe:**
- Use `@ServicesTest` (ou anotação customizada para testes de serviço).
- Use `@Import` para incluir a classe de serviço sendo testada (`{{ServiceClassName}}.class`) e quaisquer DTO Assemblers necessários (`{{ImportedAssemblers}}`).
**2. Injeção de Dependências** - **`@Autowired`:** Use para injetar beans reais do contexto Spring que são necessários para o teste, como o serviço alvo, repositórios, `ModelMapper`, e DTO Assemblers.
- Dependências a injetar: `{{AutowiredDependencies}}`.
- **`@MockBean`:** Use para mockar serviços externos ou dependências cujo comportamento precisa ser controlado (ex: serviços de pagamento, notificação, APIs de terceiros).
- Dependências a mockar: `{{MockedDependencies}}`.
**3. Configuração do Ambiente de Teste (Setup)** - **`@BeforeAll` (Setup do Banco de Dados):**
- Crie um método `static void` anotado com `@BeforeAll`.
- O método deve receber `DataSource` como parâmetro.
- Use `ScriptUtils.executeSqlScript` para executar os scripts SQL na seguinte ordem: primeiro os de domínio/suporte (`{{OtherSqlScripts}}`), depois o principal (`{{MainSqlScript}}`).
- **`@BeforeEach` (Setup por Teste):**
- Crie um método `void` anotado com `@BeforeEach`.
- Neste método, carregue entidades do banco de dados (que foram inseridas pelo `@BeforeAll`) e armazene-as em variáveis de instância da classe de teste. Isso garante que cada teste comece com um estado limpo e conhecido.
- Implemente o seguinte bloco de código:
```java
{{BeforeEachSetupCode}}
```
**4. Estrutura e Padrões dos Métodos de Teste** - **Convenção de Nomes:** Siga estritamente o padrão `metodoTestado_QuandoCondicao_DeveComportamentoEsperado()`. - **Corpo do Teste:** Utilize o padrão **Arrange-Act-Assert**. - **Asserções:** Use as asserções do `org.junit.jupiter.api.Assertions` (`assertEquals`, `assertNotNull`, `assertThrows`, etc.). - **Linguagem:** Todo o código, comentários e nomes de variáveis devem ser em português.
**5. Cenários de Teste a Serem Gerados** Gere os métodos de teste para os seguintes cenários, usando os placeholders de exceções e DTOs fornecidos.
**a) Testes de Recuperação (GET):** - `buscarPorId_QuandoIdNaoExiste_DeveLancar{{NotFoundException}}` - `buscarPorId_Quando{{EntityName}}PertenceAOutraLoja_DeveLancar{{NotFoundException}}` - `buscarPorId_Quando{{EntityName}}FoiExcluidoLogicamente_DeveLancar{{NotFoundException}}` - `buscarPorId_QuandoIdValido_DeveRetornar{{ResponseDtoName}}Corretamente`
**b) Testes de Criação (CREATE):** - `criar_QuandoDadosValidos_DeveSalvarComSucesso` - `criar_QuandoNomeJaExisteNaMesmaLoja_DeveLancar{{BusinessException}}ComMensagemEspecifica` (Mensagem: `{{UniqueConstraintMessage}}`) - `criar_QuandoForeignKeyInvalida_DeveLancar{{ForeignKeyException}}` - `criar_QuandoNomeDuplicadoEmOutraLoja_DeveSalvarComSucesso`
**c) Testes de Atualização (UPDATE):** - `atualizar_QuandoDadosValidos_DeveAlterarNoBanco` - `atualizar_Quando{{EntityName}}PertenceAOutraLoja_DeveLancar{{NotFoundException}}`
**d) Testes de Remoção (DELETE / Soft-Delete):** - `remover_Quando{{EntityName}}Valido_DevePreencherDataExclusao` - `remover_Quando{{EntityName}}NaoExiste_DeveLancar{{NotFoundException}}`
**Exemplo de Estrutura Final:** ```java package {{TestPackage}};
// imports... import static org.junit.jupiter.api.Assertions.*;
@ServicesTest @Import({{{ServiceClassName}}.class, {{ImportedAssemblers}}}) class {{ServiceClassName}}IT {
@Autowired
private {{ServiceClassName}} {{serviceInstanceName}};
// Outras dependências com @Autowired
// {{AutowiredDependencies declarations}}
// Mocks
// {{MockedDependencies declarations}}
// Variáveis de instância para dados de setup
// {{InstanceVariablesForSetup}}
@BeforeAll
static void setupDatabase(@Autowired DataSource dataSource) {
// Executar scripts SQL
}
@BeforeEach
void setupTestData() {
// Carregar dados dos repositórios para as variáveis de instância
{{BeforeEachSetupCode}}
}
@Test
@DisplayName("Deve lançar {{NotFoundException}} ao buscar por ID inexistente")
void buscarPorId_QuandoIdNaoExiste_DeveLancar{{NotFoundException}}() {
// Arrange
Long idInexistente = 999L;
// Act & Assert
assertThrows({{NotFoundException}}.class, () -> {
{{serviceInstanceName}}.buscarPorId(idInexistente);
});
}
@Test
@DisplayName("Deve salvar com sucesso um novo {{entityNameLower}} com dados válidos")
void criar_QuandoDadosValidos_DeveSalvarComSucesso() {
// Arrange
var requestDTO = new {{RequestDtoName}}();
// ... popular DTO com dados válidos
// Act
var responseDTO = {{serviceInstanceName}}.criar(requestDTO);
// Assert
assertNotNull(responseDTO);
assertNotNull(responseDTO.getId());
// ... outras asserções
}
// ... outros métodos de teste seguindo a estrutura ...
} ```