Back to Repositories

Testing Spring Boot Message Controller Implementation in spring-boot-examples

This test suite implements comprehensive web testing for a Spring Boot Thymeleaf application’s message controller functionality. It validates core message handling operations including page rendering, message creation, and form validation using MockMvc.

Test Coverage Overview

The test suite provides thorough coverage of the MessageController’s core functionalities:
  • Homepage rendering and content verification
  • Message creation with parameter validation
  • Form validation error handling
  • URL pattern matching for created messages
Integration points include Spring’s WebApplicationContext and MockMvc for simulated HTTP requests.

Implementation Analysis

The testing approach utilizes Spring’s MockMvc framework for simulating HTTP requests and validating responses. The implementation employs a combination of request builders, response matchers, and custom regex validation patterns.

Key patterns include setup configuration using WebApplicationContext, request parameter testing, and response content verification using matchers.

Technical Details

  • Testing Framework: JUnit with SpringRunner
  • Spring Test Utilities: MockMvc, WebApplicationContext
  • Custom Utilities: RegexMatcher for URL validation
  • Configuration: WebAppConfiguration, ContextConfiguration
  • Request Types: GET and POST testing

Best Practices Demonstrated

The test suite exemplifies several testing best practices in Spring Boot applications:
  • Proper test initialization and setup using @Before
  • Isolated test cases for distinct functionality
  • Custom matcher implementation for flexible validation
  • Comprehensive validation of response status, headers, and content
  • Clear test method naming conventions

ityouknow/spring-boot-examples

2.x/spring-boot-web-thymeleaf/src/test/java/com/neo/MessageControllerWebTests.java

            

package com.neo;

import java.util.regex.Pattern;

import org.hamcrest.Description;
import org.hamcrest.TypeSafeMatcher;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import static org.hamcrest.Matchers.containsString;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@RunWith(SpringRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = ThymeleafApplication.class)
public class MessageControllerWebTests {

	@Autowired
	private WebApplicationContext wac;

	private MockMvc mockMvc;

	@Before
	public void setup() {
		this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
	}

	@Test
	public void testHome() throws Exception {
		this.mockMvc.perform(get("/")).andExpect(status().isOk())
				.andExpect(content().string(containsString("<title>Messages")));
	}

	@Test
	public void testCreate() throws Exception {
		this.mockMvc.perform(post("/").param("text", "FOO text").param("summary", "FOO"))
				.andExpect(status().isFound())
				.andExpect(header().string("location", RegexMatcher.matches("/[0-9]+")));
	}

	@Test
	public void testCreateValidation() throws Exception {
		this.mockMvc.perform(post("/").param("text", "").param("summary", ""))
				.andExpect(status().isOk())
				.andExpect(content().string(containsString("is required")));
	}

	private static class RegexMatcher extends TypeSafeMatcher<String> {
		private final String regex;

		public RegexMatcher(String regex) {
			this.regex = regex;
		}

		public static org.hamcrest.Matcher<java.lang.String> matches(String regex) {
			return new RegexMatcher(regex);
		}

		@Override
		public boolean matchesSafely(String item) {
			return Pattern.compile(this.regex).matcher(item).find();
		}

		@Override
		public void describeMismatchSafely(String item, Description mismatchDescription) {
			mismatchDescription.appendText("was \"").appendText(item).appendText("\"");
		}

		@Override
		public void describeTo(Description description) {
			description.appendText("a string that matches regex: ")
					.appendText(this.regex);
		}
	}
}