Support Servlet error message in MockMvc assertions

Prior to this commit, `MockMvc` would support checking for the Servlet
error message as the "response status reason". While this error message
can be driven with the `@ResponseStatus` annotation, this message is not
technically the HTTP status reason listed on the response status line.

This message is provided by the Servlet container in the error page when
the `response.sendError(int, String)` method is used.

This commit adds the missing
`mvc.get().uri("/error/message")).hasErrorMessage("error message")`
assertion to check for this Servlet error message.

Closes gh-34016
This commit is contained in:
Brian Clozel 2024-12-11 16:00:41 +01:00
parent 41d9f21ab9
commit 52006b71bc
3 changed files with 35 additions and 0 deletions

View File

@ -22,6 +22,7 @@ import org.assertj.core.api.AbstractByteArrayAssert;
import org.assertj.core.api.AbstractStringAssert;
import org.assertj.core.api.Assertions;
import org.assertj.core.api.ByteArrayAssert;
import org.assertj.core.api.StringAssert;
import org.springframework.lang.Nullable;
import org.springframework.mock.web.MockHttpServletResponse;
@ -163,4 +164,16 @@ public abstract class AbstractMockHttpServletResponseAssert<SELF extends Abstrac
return this.myself;
}
/**
* Verify that the {@link jakarta.servlet.http.HttpServletResponse#sendError(int, String)} Servlet error message}
* is equal to the given value.
* @param errorMessage the expected Servlet error message (can be null)
* @since 6.2.1
*/
public SELF hasErrorMessage(@Nullable String errorMessage) {
new StringAssert(getResponse().getErrorMessage())
.as("Servlet error message").isEqualTo(errorMessage);
return this.myself;
}
}

View File

@ -110,6 +110,13 @@ public class AbstractMockHttpServletResponseAssertTests {
.withMessageContainingAll("Redirected URL", redirectedUrl, "another");
}
@Test
void hasServletErrorMessage() throws Exception{
MockHttpServletResponse response = new MockHttpServletResponse();
response.sendError(403, "expected error message");
assertThat(fromResponse(response)).hasErrorMessage("expected error message");
}
private MockHttpServletResponse createResponse(String body) {
try {

View File

@ -67,6 +67,7 @@ import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.context.WebApplicationContext;
@ -596,6 +597,13 @@ public class MockMvcTesterIntegrationTests {
result -> assertThat(result).hasRedirectedUrl("test"));
}
@Test
void assertErrorMessageWithUnresolvedException() {
assertThatExceptionOfType(AssertionError.class)
.isThrownBy(() -> assertThat(mvc.get().uri("/error/message")).hasErrorMessage("invalid"))
.withMessageContainingAll("[Servlet error message]", "invalid", "expected error message");
}
@Test
void assertRequestWithUnresolvedException() {
testAssertionFailureWithUnresolvableException(
@ -798,6 +806,13 @@ public class MockMvcTesterIntegrationTests {
public String validation(@PathVariable @Size(max = 4) String id) {
return "Hello " + id;
}
@GetMapping("/error/message")
@ResponseStatus(code = HttpStatus.BAD_REQUEST, reason = "expected error message")
public void errorMessage() {
}
}
}