← Spring Boot®: aplicações, contratos e operação
08 / 10 · 60 MIN

Âmbito de testes e evidência de integração

Interpreta o que cada âmbito de teste demonstra, preserva controlos de acesso e distingue rollback local de efeitos confirmados noutras threads.

Escolher o âmbito da evidência

Um teste unitário pode examinar uma regra com dependências controladas. Uma fatia WebMvcTest seleciona infraestrutura MVC e componentes relevantes, em vez de carregar indiscriminadamente toda a aplicação. SpringBootTest pode carregar um contexto mais amplo; o ambiente web escolhido determina se existe servidor real.

Escreve a conclusão pretendida antes de ler o resultado. Uma resposta JSON correta numa fatia com serviço simulado não demonstra commit, compatibilidade SQL ou acesso a uma API externa. Cada substituição reduz o âmbito da evidência, mesmo quando torna o teste rápido e útil.

Configurar uma fatia explícita

WebMvcTest pode fornecer MockMvc e apoio de segurança quando as dependências relevantes estão presentes. Importar a SecurityConfiguration que se pretende avaliar torna a política explícita. MockitoBean fornece ao controller um colaborador controlado; o comportamento configurado desse mock faz parte das premissas do resultado.

No Boot 4, usa os módulos e packages correspondentes à versão escolhida. O exemplo importa WebMvcTest de org.springframework.boot.webmvc.test.autoconfigure e MockitoBean de org.springframework.test.context.bean.override.mockito. Não transfiras imports antigos sem confirmar a API usada pelo projeto.

Uma identidade simulada não é login

WithMockUser coloca uma identidade no contexto de segurança do teste. O utilizador não precisa de existir na base e a sua palavra-passe não passa pelo mecanismo de autenticação real. O atributo authorities permite fornecer REPORT_WRITE literalmente; roles usa a convenção de prefixo ROLE_.

Isto é útil para comparar decisões de autorização com identidades controladas. Não demonstra a validação de uma palavra-passe, a assinatura de um JWT ou a disponibilidade do emissor. Mantém essas conclusões associadas a evidência própria, em vez de as deduzir de um controller autorizado com principal simulado.

Isolar o motivo de rejeição

Uma rejeição 403 pode resultar de autoridade insuficiente ou de CSRF, entre outras causas configuradas. Para comparar REPORT_WRITE com REPORT_READ num POST protegido, fornece token válido a ambos. Acrescenta uma comparação em que a autoridade é suficiente e o token está ausente ou é inválido.

A verificação deve também observar o efeito: numa rejeição anterior ao controller, o serviço simulado não deve ser chamado. Um caso positivo impede que uma política que bloqueia tudo pareça correta. Desativar filtros pode ser adequado a outro âmbito, mas deixa de sustentar conclusões sobre esses controlos.

Servidor real e dados isolados

SpringBootTest com MOCK não inicia normalmente um servidor embebido. RANDOM_PORT inicia um servidor numa porta atribuída e permite pedidos HTTP reais nesse ambiente. Isso acrescenta uma fronteira de execução: cliente e servidor trabalham em threads distintas e podem usar transações distintas.

Transactional no método do teste não reverte automaticamente os commits realizados pelo servidor. Se a comparação seguinte usa a mesma base, precisa de isolamento e limpeza explícitos. Mudar a porta não limpa registos. Distingue também este servidor local de um percurso real por gateway, TLS e balanceador externos.

Observar sincronização e confirmação

Num teste ORM, persist pode alterar o contexto sem enviar imediatamente todo o SQL. Se o teste termina com rollback antes da sincronização relevante, uma restrição da base pode nunca ser observada. Um flush explícito no ponto adequado permite verificar esse comportamento, sem equivaler a uma confirmação final da transação.

O estado da transação gerida pelo teste está associado à thread. Um timeout preemptivo que execute a ação noutra thread pode deixar efeitos confirmados fora do rollback esperado. Ao analisar um teste verde, pergunta que SQL foi observado, em que thread correu e que efeitos ficaram por limpar.

Interpretar a matriz do exemplo

O exemplo fornece o contrato ReportService, um controller que o invoca e três comparações com a política da aula anterior. O serviço é substituído em cada teste. permitsWriter combina REPORT_WRITE e csrf(); rejectsReader conserva csrf() e muda a autoridade; rejectsMissingCsrf mantém REPORT_WRITE e omite o token.

A distinção permite atribuir cada expectativa ao controlo relevante. A string de sucesso vem do mock e não certifica publicação nem persistência. A avaliação pede escolher interpretações, limites e próximos passos a partir do excerto; não exige executar JUnit, lançar um servidor ou escrever código.

// Separate files in package com.acme.reports.
// Uses SecurityConfiguration from the preceding lesson.
// Test dependencies: Boot 4.1.1 MVC test support, Spring Security test,
// JUnit Jupiter and Mockito. Read the snippet; execution is not assessed.
// ReportService.java
package com.acme.reports;
public interface ReportService { String publish(); }

// ReportController.java
package com.acme.reports;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ReportController {
  private final ReportService service;
  public ReportController(ReportService service) { this.service = service; }
  @PostMapping(path = "/reports/publish", produces = "text/plain")
  public String publish() { return service.publish(); }
}

// ReportControllerTests.java
package com.acme.reports;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest;
import org.springframework.context.annotation.Import;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.test.web.servlet.MockMvc;
import static org.mockito.Mockito.*;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@WebMvcTest(ReportController.class)
@Import(SecurityConfiguration.class)
class ReportControllerTests {
  @Autowired MockMvc mvc;
  @MockitoBean ReportService service;

  @Test @WithMockUser(authorities = "REPORT_WRITE")
  void permitsWriter() throws Exception {
    when(service.publish()).thenReturn("accepted-in-test");
    mvc.perform(post("/reports/publish").with(csrf()))
        .andExpect(status().isOk())
        .andExpect(content().string("accepted-in-test"));
    verify(service).publish();
  }

  @Test @WithMockUser(authorities = "REPORT_READ")
  void rejectsReader() throws Exception {
    mvc.perform(post("/reports/publish").with(csrf()))
        .andExpect(status().isForbidden());
    verifyNoInteractions(service);
  }

  @Test @WithMockUser(authorities = "REPORT_WRITE")
  void rejectsMissingCsrf() throws Exception {
    mvc.perform(post("/reports/publish"))
        .andExpect(status().isForbidden());
    verifyNoInteractions(service);
  }
}
NA PRÁTICA

Compara os três métodos sem os executar. O primeiro combina autoridade suficiente e token válido; o segundo muda apenas a autoridade; o terceiro conserva a autoridade suficiente e omite o token. O retorno accepted-in-test é definido pelo mock e não prova que um relatório foi gravado.

Armadilhas comuns

Interpretar WithMockUser como login; desligar filtros para obter verde; atribuir qualquer 403 à autoridade; presumir rollback do servidor a partir de Transactional no cliente; confundir flush com commit.

Tópicos relacionados: Segurança e fronteiras de autorização · Persistência e fronteiras de transação · Empacotamento, entrega e aceitação operacional

Leva esta ideia contigo

Um resultado só sustenta o âmbito que foi exercitado. Explicita substituições, controlos ativos, threads e transações antes de concluir que o comportamento completo está validado.

Criar conta

Referência: Testing Spring Boot applications · Spring Boot 4.1.1 / Spring Framework 7.0.9 / Java 25