CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-springframework-boot--spring-boot-starter-web

Starter for building web, including RESTful, applications using Spring MVC with embedded Tomcat server.

Pending
Overview
Eval results
Files

testing.mddocs/

Web Testing

Spring Boot provides comprehensive testing support for web applications with dedicated annotations and testing utilities for controllers, web layers, and full integration testing.

Capabilities

@WebMvcTest Integration

Test Spring MVC controllers with focused test slicing that loads only web layer components.

/**
 * Web MVC test annotation for controller testing
 */
@WebMvcTest(UserController.class)
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class UserControllerTest {
    
    @Autowired
    private MockMvc mockMvc;
    
    @MockBean
    private UserService userService;
    
    @Test
    void shouldGetUser() throws Exception {
        // Test implementation
    }
}

/**
 * Web MVC test for all controllers
 */
@WebMvcTest
class AllControllersTest {
    @Autowired
    private MockMvc mockMvc;
}

Usage Examples:

@WebMvcTest(ProductController.class)
class ProductControllerTest {
    
    @Autowired
    private MockMvc mockMvc;
    
    @MockBean
    private ProductService productService;
    
    @Autowired
    private ObjectMapper objectMapper;
    
    @Test
    void shouldCreateProduct() throws Exception {
        Product product = new Product("Test Product", 29.99);
        Product savedProduct = new Product(1L, "Test Product", 29.99);
        
        when(productService.save(any(Product.class))).thenReturn(savedProduct);
        
        mockMvc.perform(post("/api/products")
                .contentType(MediaType.APPLICATION_JSON)
                .content(objectMapper.writeValueAsString(product)))
                .andExpect(status().isCreated())
                .andExpect(jsonPath("$.id").value(1))
                .andExpect(jsonPath("$.name").value("Test Product"))
                .andExpect(jsonPath("$.price").value(29.99));
    }
    
    @Test
    void shouldGetProduct() throws Exception {
        Product product = new Product(1L, "Test Product", 29.99);
        when(productService.findById(1L)).thenReturn(product);
        
        mockMvc.perform(get("/api/products/1"))
                .andExpect(status().isOk())
                .andExpect(content().contentType(MediaType.APPLICATION_JSON))
                .andExpect(jsonPath("$.name").value("Test Product"));
    }
    
    @Test
    void shouldReturnNotFoundForNonExistentProduct() throws Exception {
        when(productService.findById(999L)).thenThrow(new ProductNotFoundException());
        
        mockMvc.perform(get("/api/products/999"))
                .andExpect(status().isNotFound());
    }
}

MockMvc Testing

Comprehensive MockMvc API for testing web layer interactions.

/**
 * MockMvc request builders and matchers
 */
public class MockMvcRequestBuilders {
    public static MockHttpServletRequestBuilder get(String urlTemplate, Object... uriVars);
    public static MockHttpServletRequestBuilder post(String urlTemplate, Object... uriVars);
    public static MockHttpServletRequestBuilder put(String urlTemplate, Object... uriVars);
    public static MockHttpServletRequestBuilder delete(String urlTemplate, Object... uriVars);
    public static MockHttpServletRequestBuilder patch(String urlTemplate, Object... uriVars);
}

/**
 * Request customization
 */
public interface MockHttpServletRequestBuilder {
    MockHttpServletRequestBuilder contentType(MediaType mediaType);
    MockHttpServletRequestBuilder content(String content);
    MockHttpServletRequestBuilder header(String name, Object... values);
    MockHttpServletRequestBuilder headers(HttpHeaders httpHeaders);
    MockHttpServletRequestBuilder param(String name, String... values);
    MockHttpServletRequestBuilder cookie(Cookie... cookies);
    MockHttpServletRequestBuilder sessionAttr(String name, Object value);
    MockHttpServletRequestBuilder principal(Principal principal);
}

/**
 * Response verification
 */
public class MockMvcResultMatchers {
    public static StatusResultMatchers status();
    public static ContentResultMatchers content();
    public static JsonPathResultMatchers jsonPath(String expression, Object... args);
    public static HeaderResultMatchers header();
    public static ModelResultMatchers model();
    public static ViewResultMatchers view();
    public static RedirectResultMatchers redirectedUrl(String expectedUrl);
}

Usage Examples:

@Test
void shouldHandleFormSubmission() throws Exception {
    mockMvc.perform(post("/users")
            .param("name", "John Doe")
            .param("email", "john@example.com")
            .contentType(MediaType.APPLICATION_FORM_URLENCODED))
            .andExpect(status().is3xxRedirection())
            .andExpect(redirectedUrl("/users/success"));
}

@Test
void shouldHandleFileUpload() throws Exception {
    MockMultipartFile file = new MockMultipartFile(
            "file", "test.txt", "text/plain", "Hello, World!".getBytes());
    
    mockMvc.perform(multipart("/api/upload")
            .file(file)
            .param("description", "Test file"))
            .andExpect(status().isOk())
            .andExpect(content().string(containsString("File uploaded")));
}

@Test
void shouldValidateRequestBody() throws Exception {
    Product invalidProduct = new Product("", -10.0); // Invalid data
    
    mockMvc.perform(post("/api/products")
            .contentType(MediaType.APPLICATION_JSON)
            .content(objectMapper.writeValueAsString(invalidProduct)))
            .andExpect(status().isBadRequest())
            .andExpect(jsonPath("$.name").value("Name is required"))
            .andExpect(jsonPath("$.price").value("Price must be positive"));
}

Integration Testing

Full application context testing with @SpringBootTest and TestRestTemplate.

/**
 * Full integration test with embedded server
 */
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class UserIntegrationTest {
    
    @Autowired
    private TestRestTemplate restTemplate;
    
    @LocalServerPort
    private int port;
    
    @Test
    void shouldCreateAndRetrieveUser() {
        // Integration test implementation
    }
}

/**
 * Integration test with mock web environment
 */
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
@AutoConfigureTestDatabase
class UserRepositoryIntegrationTest {
    
    @Autowired
    private MockMvc mockMvc;
    
    @Autowired
    private UserRepository userRepository;
}

Usage Examples:

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@TestPropertySource(locations = "classpath:application-test.properties")
class ProductIntegrationTest {
    
    @Autowired
    private TestRestTemplate restTemplate;
    
    @Autowired
    private ProductRepository productRepository;
    
    @LocalServerPort
    private int port;
    
    @Test
    void shouldCreateProductThroughApi() {
        Product product = new Product("Integration Test Product", 39.99);
        
        ResponseEntity<Product> response = restTemplate.postForEntity(
                "/api/products", product, Product.class);
        
        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.CREATED);
        assertThat(response.getBody().getId()).isNotNull();
        assertThat(response.getBody().getName()).isEqualTo("Integration Test Product");
        
        // Verify in database
        Optional<Product> savedProduct = productRepository.findById(response.getBody().getId());
        assertThat(savedProduct).isPresent();
    }
    
    @Test
    void shouldGetProductList() {
        // Seed test data
        productRepository.save(new Product("Product 1", 10.0));
        productRepository.save(new Product("Product 2", 20.0));
        
        ResponseEntity<Product[]> response = restTemplate.getForEntity(
                "/api/products", Product[].class);
        
        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
        assertThat(response.getBody()).hasSize(2);
    }
}

Test Security Configuration

Testing with Spring Security integration and authentication.

/**
 * Security testing with @WithMockUser
 */
@WebMvcTest(SecureController.class)
class SecureControllerTest {
    
    @Autowired
    private MockMvc mockMvc;
    
    @Test
    @WithMockUser(roles = "ADMIN")
    void shouldAllowAdminAccess() throws Exception {
        mockMvc.perform(get("/admin/users"))
                .andExpect(status().isOk());
    }
    
    @Test
    @WithMockUser(roles = "USER")
    void shouldDenyUserAccess() throws Exception {
        mockMvc.perform(get("/admin/users"))
                .andExpect(status().isForbidden());
    }
    
    @Test
    void shouldRequireAuthentication() throws Exception {
        mockMvc.perform(get("/admin/users"))
                .andExpect(status().isUnauthorized());
    }
}

/**
 * Custom security test user
 */
@WithMockUser(username = "testuser", roles = {"USER", "ADMIN"})
@Test
void shouldAllowCustomUser() throws Exception {
    // Test with custom user
}

Test Configuration and Profiles

Configure test-specific beans and properties.

/**
 * Test configuration class
 */
@TestConfiguration
public class TestConfig {
    
    @Bean
    @Primary
    public Clock testClock() {
        return Clock.fixed(Instant.parse("2023-01-01T00:00:00Z"), ZoneOffset.UTC);
    }
    
    @Bean
    @Primary
    public EmailService mockEmailService() {
        return Mockito.mock(EmailService.class);
    }
}

/**
 * Import test configuration
 */
@WebMvcTest
@Import(TestConfig.class)
class ControllerWithTestConfigTest {
    // Test with custom configuration
}

Types

// MockMvc for web layer testing
public class MockMvc {
    public ResultActions perform(MockHttpServletRequestBuilder requestBuilder) throws Exception;
}

// Test result actions for chaining expectations
public interface ResultActions {
    ResultActions andExpect(ResultMatcher matcher) throws Exception;
    ResultActions andDo(ResultHandler handler) throws Exception;
    MvcResult andReturn() throws Exception;
}

// Test RestTemplate for integration testing
public class TestRestTemplate {
    public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables);
    public <T> ResponseEntity<T> postForEntity(String url, Object request, Class<T> responseType, Object... uriVariables);
    public <T> ResponseEntity<T> exchange(String url, HttpMethod method, HttpEntity<?> requestEntity, Class<T> responseType, Object... uriVariables);
}

// Test annotations
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@ExtendWith(SpringExtension.class)
public @interface WebMvcTest {
    Class<?>[] value() default {};
    Class<?>[] controllers() default {};
    boolean useDefaultFilters() default true;
}

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@ExtendWith(SpringExtension.class)
public @interface SpringBootTest {
    WebEnvironment webEnvironment() default WebEnvironment.MOCK;
    
    enum WebEnvironment {
        MOCK, RANDOM_PORT, DEFINED_PORT, NONE
    }
}

// Mock annotations
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface MockBean {
}

@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface SpyBean {
}

// Security testing annotation
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface WithMockUser {
    String value() default "user";
    String username() default "";
    String[] roles() default {"USER"};
    String[] authorities() default {};
}

Install with Tessl CLI

npx tessl i tessl/maven-org-springframework-boot--spring-boot-starter-web

docs

configuration.md

controllers.md

embedded-server.md

error-handling.md

http-clients.md

index.md

json-processing.md

static-resources.md

testing.md

tile.json