diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/client/standalone/resultmatches/StatusAssertionTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/client/standalone/resultmatches/StatusAssertionTests.java index a2c7fc39f4..9358e18be4 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/client/standalone/resultmatches/StatusAssertionTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/client/standalone/resultmatches/StatusAssertionTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,20 +20,23 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; import org.springframework.core.annotation.AliasFor; import org.springframework.http.HttpStatus; -import org.springframework.stereotype.Controller; import org.springframework.test.web.reactive.server.WebTestClient; import org.springframework.test.web.servlet.client.MockMvcWebTestClient; +import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; import static org.hamcrest.Matchers.equalTo; +import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; import static org.springframework.http.HttpStatus.BAD_REQUEST; import static org.springframework.http.HttpStatus.CREATED; import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; +import static org.springframework.http.HttpStatus.I_AM_A_TEAPOT; import static org.springframework.http.HttpStatus.NOT_IMPLEMENTED; /** @@ -41,30 +44,34 @@ import static org.springframework.http.HttpStatus.NOT_IMPLEMENTED; * {@link org.springframework.test.web.servlet.samples.standalone.resultmatchers.StatusAssertionTests}. * * @author Rossen Stoyanchev + * @author Sam Brannen */ -public class StatusAssertionTests { +@TestInstance(PER_CLASS) +class StatusAssertionTests { private final WebTestClient testClient = MockMvcWebTestClient.bindToController(new StatusController()).build(); @Test - public void testStatusInt() { - testClient.get().uri("/created").exchange().expectStatus().isEqualTo(201); - testClient.get().uri("/createdWithComposedAnnotation").exchange().expectStatus().isEqualTo(201); - testClient.get().uri("/badRequest").exchange().expectStatus().isEqualTo(400); + void statusInt() { + testClient.get().uri("/teaPot").exchange().expectStatus().isEqualTo(I_AM_A_TEAPOT.value()); + testClient.get().uri("/created").exchange().expectStatus().isEqualTo(CREATED.value()); + testClient.get().uri("/createdWithComposedAnnotation").exchange().expectStatus().isEqualTo(CREATED.value()); + testClient.get().uri("/badRequest").exchange().expectStatus().isEqualTo(BAD_REQUEST.value()); + testClient.get().uri("/throwsException").exchange().expectStatus().isEqualTo(I_AM_A_TEAPOT.value()); } @Test - public void testHttpStatus() { + void httpStatus() { testClient.get().uri("/created").exchange().expectStatus().isCreated(); testClient.get().uri("/createdWithComposedAnnotation").exchange().expectStatus().isCreated(); testClient.get().uri("/badRequest").exchange().expectStatus().isBadRequest(); } @Test - public void testMatcher() { - testClient.get().uri("/badRequest").exchange().expectStatus().value(equalTo(400)); + void matcher() { + testClient.get().uri("/badRequest").exchange().expectStatus().value(equalTo(BAD_REQUEST.value())); } @@ -80,26 +87,41 @@ public class StatusAssertionTests { HttpStatus status() default INTERNAL_SERVER_ERROR; } - @Controller + @RestController + @ResponseStatus(I_AM_A_TEAPOT) private static class StatusController { + @RequestMapping("/teaPot") + void teaPot() { + } + @RequestMapping("/created") @ResponseStatus(CREATED) - public @ResponseBody void created(){ + void created(){ } @Get(path = "/createdWithComposedAnnotation", status = CREATED) - public @ResponseBody void createdWithComposedAnnotation() { + void createdWithComposedAnnotation() { } @RequestMapping("/badRequest") @ResponseStatus(code = BAD_REQUEST, reason = "Expired token") - public @ResponseBody void badRequest(){ + void badRequest(){ } @RequestMapping("/notImplemented") @ResponseStatus(NOT_IMPLEMENTED) - public @ResponseBody void notImplemented(){ + void notImplemented(){ + } + + @RequestMapping("/throwsException") + @ResponseStatus(NOT_IMPLEMENTED) + void throwsException() { + throw new IllegalStateException(); + } + + @ExceptionHandler + void exceptionHandler(IllegalStateException ex) { } } diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/StatusAssertionTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/StatusAssertionTests.java index 882621bc44..a1b7291e77 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/StatusAssertionTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/StatusAssertionTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,20 +20,23 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; import org.springframework.core.annotation.AliasFor; import org.springframework.http.HttpStatus; -import org.springframework.stereotype.Controller; import org.springframework.test.web.servlet.MockMvc; +import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; import static org.hamcrest.Matchers.endsWith; import static org.hamcrest.Matchers.equalTo; +import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; import static org.springframework.http.HttpStatus.BAD_REQUEST; import static org.springframework.http.HttpStatus.CREATED; import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; +import static org.springframework.http.HttpStatus.I_AM_A_TEAPOT; import static org.springframework.http.HttpStatus.NOT_IMPLEMENTED; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -45,39 +48,40 @@ import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standal * @author Rossen Stoyanchev * @author Sam Brannen */ -public class StatusAssertionTests { +@TestInstance(PER_CLASS) +class StatusAssertionTests { private final MockMvc mockMvc = standaloneSetup(new StatusController()).build(); @Test - public void testStatusInt() throws Exception { - this.mockMvc.perform(get("/created")).andExpect(status().is(201)); - this.mockMvc.perform(get("/createdWithComposedAnnotation")).andExpect(status().is(201)); - this.mockMvc.perform(get("/badRequest")).andExpect(status().is(400)); - } - - @Test - public void testHttpStatus() throws Exception { + void httpStatus() throws Exception { this.mockMvc.perform(get("/created")).andExpect(status().isCreated()); this.mockMvc.perform(get("/createdWithComposedAnnotation")).andExpect(status().isCreated()); this.mockMvc.perform(get("/badRequest")).andExpect(status().isBadRequest()); } @Test - public void testMatcher() throws Exception { - this.mockMvc.perform(get("/badRequest")).andExpect(status().is(equalTo(400))); + void statusCode() throws Exception { + this.mockMvc.perform(get("/teaPot")).andExpect(status().is(I_AM_A_TEAPOT.value())); + this.mockMvc.perform(get("/created")).andExpect(status().is(CREATED.value())); + this.mockMvc.perform(get("/createdWithComposedAnnotation")).andExpect(status().is(CREATED.value())); + this.mockMvc.perform(get("/badRequest")).andExpect(status().is(BAD_REQUEST.value())); + this.mockMvc.perform(get("/throwsException")).andExpect(status().is(I_AM_A_TEAPOT.value())); } @Test - public void testReasonEqualTo() throws Exception { + void statusCodeWithMatcher() throws Exception { + this.mockMvc.perform(get("/badRequest")).andExpect(status().is(equalTo(BAD_REQUEST.value()))); + } + + @Test + void reason() throws Exception { this.mockMvc.perform(get("/badRequest")).andExpect(status().reason("Expired token")); - - // Hamcrest matchers... - this.mockMvc.perform(get("/badRequest")).andExpect(status().reason(equalTo("Expired token"))); } @Test - public void testReasonMatcher() throws Exception { + void reasonWithMatcher() throws Exception { + this.mockMvc.perform(get("/badRequest")).andExpect(status().reason(equalTo("Expired token"))); this.mockMvc.perform(get("/badRequest")).andExpect(status().reason(endsWith("token"))); } @@ -94,26 +98,41 @@ public class StatusAssertionTests { HttpStatus status() default INTERNAL_SERVER_ERROR; } - @Controller + @RestController + @ResponseStatus(I_AM_A_TEAPOT) private static class StatusController { + @RequestMapping("/teaPot") + void teaPot() { + } + @RequestMapping("/created") @ResponseStatus(CREATED) - public @ResponseBody void created(){ + void created() { } @Get(path = "/createdWithComposedAnnotation", status = CREATED) - public @ResponseBody void createdWithComposedAnnotation() { + void createdWithComposedAnnotation() { } @RequestMapping("/badRequest") @ResponseStatus(code = BAD_REQUEST, reason = "Expired token") - public @ResponseBody void badRequest(){ + void badRequest() { } @RequestMapping("/notImplemented") @ResponseStatus(NOT_IMPLEMENTED) - public @ResponseBody void notImplemented(){ + void notImplemented() { + } + + @RequestMapping("/throwsException") + @ResponseStatus(NOT_IMPLEMENTED) + void throwsException() { + throw new IllegalStateException(); + } + + @ExceptionHandler + void exceptionHandler(IllegalStateException ex) { } } diff --git a/spring-web/src/main/java/org/springframework/web/bind/annotation/ResponseStatus.java b/spring-web/src/main/java/org/springframework/web/bind/annotation/ResponseStatus.java index c1f241afcf..999348c91b 100644 --- a/spring-web/src/main/java/org/springframework/web/bind/annotation/ResponseStatus.java +++ b/spring-web/src/main/java/org/springframework/web/bind/annotation/ResponseStatus.java @@ -79,6 +79,8 @@ public @interface ResponseStatus { /** * The reason to be used for the response. + *

Defaults to an empty string which will be ignored. Set the reason to a + * non-empty value to have it used for the response. * @see javax.servlet.http.HttpServletResponse#sendError(int, String) */ String reason() default "";