Back to Repositories

Testing Thymeleaf Message Controller Integration in spring-boot-examples

This test suite validates the functionality of a Message Controller in a Spring Boot Thymeleaf application using MockMvc for web layer testing. It focuses on testing HTTP endpoints for message creation and validation, demonstrating comprehensive web controller testing practices.

Test Coverage Overview

The test suite provides comprehensive coverage of the Message Controller’s core functionality.

  • Tests the home endpoint (‘/’) for successful page rendering
  • Validates message creation with proper parameters
  • Verifies form validation for empty submissions
  • Covers response status codes, headers, and content validation

Implementation Analysis

The testing approach utilizes Spring’s MockMvc framework for simulating HTTP requests without a full server deployment.

The implementation leverages Spring’s test context framework with @WebAppConfiguration and @ContextConfiguration annotations. A custom RegexMatcher class extends TypeSafeMatcher for flexible response validation patterns.

  • Uses SpringRunner for test execution
  • Implements setup with WebApplicationContext
  • Employs fluent assertion style with MockMvc

Technical Details

  • Spring Test Context framework
  • JUnit 4 testing framework
  • MockMvc for web layer testing
  • Hamcrest matchers for assertions
  • Custom regex matching utility
  • WebApplicationContext configuration

Best Practices Demonstrated

The test suite exemplifies several testing best practices in Spring Boot applications.

  • Proper test setup and context configuration
  • Isolated web layer testing
  • Comprehensive validation scenarios
  • Custom matcher implementation for flexible assertions
  • Clear test method naming conventions
  • Efficient test context reuse

ityouknow/spring-boot-examples

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);
		}
	}
}