Pular para conteúdo

Padrões de Testes Java

Este documento define o padrão Arkorizon para testes em projetos Java.

O objetivo é garantir feedback rápido, confiança em regras de negócio e cobertura útil sem transformar testes em burocracia.

Pirâmide de testes

Prioridade:

  1. Testes unitários rápidos.
  2. Testes de adapter com slice do Spring quando necessário.
  3. Testes de integração para fluxos críticos.
  4. Testes end-to-end apenas para jornadas essenciais.

Use cases

Use cases devem ser testados sem subir Spring.

class LoginUseCaseImplTest {

    private final FindUserByEmailPort findUserByEmailPort = mock(FindUserByEmailPort.class);
    private final PasswordVerifierPort passwordVerifierPort = mock(PasswordVerifierPort.class);
    private final TokenIssuerPort tokenIssuerPort = mock(TokenIssuerPort.class);

    private final LoginUseCase loginUseCase = new LoginUseCaseImpl(
            findUserByEmailPort,
            passwordVerifierPort,
            tokenIssuerPort
    );

    @Test
    void shouldRejectInactiveUser() {
        // Test behavior
    }
}

Regras:

  • Não usar @SpringBootTest para testar use case puro.
  • Mockar output ports.
  • Validar comportamento, não detalhes internos.
  • Testar cenários de sucesso e falha.

Domain models

Domain models com regra devem ter testes próprios.

class UserTest {

    @Test
    void shouldRejectLoginWhenUserIsInactive() {
        // Test invariant
    }
}

Controllers

Controllers podem ser testados com @WebMvcTest.

@WebMvcTest(AuthController.class)
class AuthControllerTest {
}

Objetivo:

  • validar status HTTP;
  • validar request/response;
  • validar Bean Validation;
  • validar mapeamento de erros web.

Não teste regra de negócio no controller.

Persistence adapters

Persistence adapters podem usar:

  • @DataJpaTest para testes JPA;
  • Testcontainers para comportamento real com PostgreSQL;
  • migrations reais quando aplicável.

Objetivo:

  • validar queries;
  • validar mapping entity/domain;
  • validar constraints relevantes;
  • validar integração com banco real quando necessário.

External adapters

Adapters de APIs externas devem usar mocks de contrato ou servidores fake.

Opções:

  • WireMock;
  • MockWebServer;
  • contract tests;
  • fake implementation em teste.

Não dependa de API externa real em teste automatizado comum.

Nomenclatura de testes

Classes de teste devem usar sufixo Test.

LoginUseCaseImplTest
UserPersistenceAdapterTest
AuthControllerTest

Métodos devem descrever comportamento.

shouldReturnTokenWhenCredentialsAreValid
shouldRejectInactiveUser
shouldReturnUnauthorizedWhenPasswordIsInvalid

Estrutura AAA

Use o padrão Arrange, Act, Assert.

@Test
void shouldNormalizeEmailBeforeLookup() {
    // Arrange
    final LoginCommand command = new LoginCommand("USER@ARKORIZON.COM", "secret");

    // Act
    final AuthTokenResult result = loginUseCase.execute(command);

    // Assert
    assertNotNull(result);
}

Comentários Arrange, Act, Assert são opcionais. Use quando deixarem o teste mais legível.

O que testar

Teste:

  • regra de negócio;
  • validação relevante;
  • erro esperado;
  • integração crítica;
  • mapping importante;
  • queries customizadas;
  • comportamento de adapters.

Evite testar:

  • getters e setters triviais;
  • código gerado;
  • detalhes internos sem valor de comportamento;
  • mocks que apenas repetem a implementação.

Test data builders

Use builders para reduzir repetição em cenários complexos.

final User user = UserTestBuilder.activeUser()
        .withEmail("user@arkorizon.com")
        .build();

Builders de teste devem ficar no pacote de testes.

Assertions

Use assertions claras.

assertEquals("user@arkorizon.com", user.email());
assertThrows(InvalidCredentialsException.class, () -> loginUseCase.execute(command));

Quando o projeto usar AssertJ, prefira:

assertThat(user.email()).isEqualTo("user@arkorizon.com");

Cobertura

Cobertura é métrica auxiliar, não objetivo final.

Priorize cobertura de:

  • use cases;
  • regras de domínio;
  • adapters críticos;
  • fluxos de erro;
  • integrações sensíveis.

Não busque 100% de cobertura com testes artificiais.

Checklist de revisão de testes

  • Use cases são testados sem Spring.
  • Cenários de falha foram cobertos.
  • Testes têm nomes claros.
  • Testes validam comportamento observável.
  • Mocks não repetem a implementação.
  • Integrações críticas usam teste adequado.
  • Testes não dependem de ordem de execução.
  • Testes não usam dados reais sensíveis.