Polish @ResponseStatus javadoc and StatusAssertionTests

This commit is contained in:
Sam Brannen 2021-06-08 18:47:04 +02:00
parent f3db6b996d
commit 000b6a7e95
3 changed files with 83 additions and 40 deletions

View File

@ -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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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 java.lang.annotation.RetentionPolicy;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.springframework.core.annotation.AliasFor; import org.springframework.core.annotation.AliasFor;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.test.web.reactive.server.WebTestClient; import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.test.web.servlet.client.MockMvcWebTestClient; 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.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import static org.hamcrest.Matchers.equalTo; 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.BAD_REQUEST;
import static org.springframework.http.HttpStatus.CREATED; import static org.springframework.http.HttpStatus.CREATED;
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; 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.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}. * {@link org.springframework.test.web.servlet.samples.standalone.resultmatchers.StatusAssertionTests}.
* *
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
* @author Sam Brannen
*/ */
public class StatusAssertionTests { @TestInstance(PER_CLASS)
class StatusAssertionTests {
private final WebTestClient testClient = private final WebTestClient testClient =
MockMvcWebTestClient.bindToController(new StatusController()).build(); MockMvcWebTestClient.bindToController(new StatusController()).build();
@Test @Test
public void testStatusInt() { void statusInt() {
testClient.get().uri("/created").exchange().expectStatus().isEqualTo(201); testClient.get().uri("/teaPot").exchange().expectStatus().isEqualTo(I_AM_A_TEAPOT.value());
testClient.get().uri("/createdWithComposedAnnotation").exchange().expectStatus().isEqualTo(201); testClient.get().uri("/created").exchange().expectStatus().isEqualTo(CREATED.value());
testClient.get().uri("/badRequest").exchange().expectStatus().isEqualTo(400); 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 @Test
public void testHttpStatus() { void httpStatus() {
testClient.get().uri("/created").exchange().expectStatus().isCreated(); testClient.get().uri("/created").exchange().expectStatus().isCreated();
testClient.get().uri("/createdWithComposedAnnotation").exchange().expectStatus().isCreated(); testClient.get().uri("/createdWithComposedAnnotation").exchange().expectStatus().isCreated();
testClient.get().uri("/badRequest").exchange().expectStatus().isBadRequest(); testClient.get().uri("/badRequest").exchange().expectStatus().isBadRequest();
} }
@Test @Test
public void testMatcher() { void matcher() {
testClient.get().uri("/badRequest").exchange().expectStatus().value(equalTo(400)); testClient.get().uri("/badRequest").exchange().expectStatus().value(equalTo(BAD_REQUEST.value()));
} }
@ -80,26 +87,41 @@ public class StatusAssertionTests {
HttpStatus status() default INTERNAL_SERVER_ERROR; HttpStatus status() default INTERNAL_SERVER_ERROR;
} }
@Controller @RestController
@ResponseStatus(I_AM_A_TEAPOT)
private static class StatusController { private static class StatusController {
@RequestMapping("/teaPot")
void teaPot() {
}
@RequestMapping("/created") @RequestMapping("/created")
@ResponseStatus(CREATED) @ResponseStatus(CREATED)
public @ResponseBody void created(){ void created(){
} }
@Get(path = "/createdWithComposedAnnotation", status = CREATED) @Get(path = "/createdWithComposedAnnotation", status = CREATED)
public @ResponseBody void createdWithComposedAnnotation() { void createdWithComposedAnnotation() {
} }
@RequestMapping("/badRequest") @RequestMapping("/badRequest")
@ResponseStatus(code = BAD_REQUEST, reason = "Expired token") @ResponseStatus(code = BAD_REQUEST, reason = "Expired token")
public @ResponseBody void badRequest(){ void badRequest(){
} }
@RequestMapping("/notImplemented") @RequestMapping("/notImplemented")
@ResponseStatus(NOT_IMPLEMENTED) @ResponseStatus(NOT_IMPLEMENTED)
public @ResponseBody void notImplemented(){ void notImplemented(){
}
@RequestMapping("/throwsException")
@ResponseStatus(NOT_IMPLEMENTED)
void throwsException() {
throw new IllegalStateException();
}
@ExceptionHandler
void exceptionHandler(IllegalStateException ex) {
} }
} }

View File

@ -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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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 java.lang.annotation.RetentionPolicy;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.springframework.core.annotation.AliasFor; import org.springframework.core.annotation.AliasFor;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.test.web.servlet.MockMvc; 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.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus; 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.endsWith;
import static org.hamcrest.Matchers.equalTo; 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.BAD_REQUEST;
import static org.springframework.http.HttpStatus.CREATED; import static org.springframework.http.HttpStatus.CREATED;
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; 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.http.HttpStatus.NOT_IMPLEMENTED;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 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 Rossen Stoyanchev
* @author Sam Brannen * @author Sam Brannen
*/ */
public class StatusAssertionTests { @TestInstance(PER_CLASS)
class StatusAssertionTests {
private final MockMvc mockMvc = standaloneSetup(new StatusController()).build(); private final MockMvc mockMvc = standaloneSetup(new StatusController()).build();
@Test @Test
public void testStatusInt() throws Exception { void httpStatus() 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 {
this.mockMvc.perform(get("/created")).andExpect(status().isCreated()); this.mockMvc.perform(get("/created")).andExpect(status().isCreated());
this.mockMvc.perform(get("/createdWithComposedAnnotation")).andExpect(status().isCreated()); this.mockMvc.perform(get("/createdWithComposedAnnotation")).andExpect(status().isCreated());
this.mockMvc.perform(get("/badRequest")).andExpect(status().isBadRequest()); this.mockMvc.perform(get("/badRequest")).andExpect(status().isBadRequest());
} }
@Test @Test
public void testMatcher() throws Exception { void statusCode() throws Exception {
this.mockMvc.perform(get("/badRequest")).andExpect(status().is(equalTo(400))); 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 @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")); this.mockMvc.perform(get("/badRequest")).andExpect(status().reason("Expired token"));
// Hamcrest matchers...
this.mockMvc.perform(get("/badRequest")).andExpect(status().reason(equalTo("Expired token")));
} }
@Test @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"))); this.mockMvc.perform(get("/badRequest")).andExpect(status().reason(endsWith("token")));
} }
@ -94,26 +98,41 @@ public class StatusAssertionTests {
HttpStatus status() default INTERNAL_SERVER_ERROR; HttpStatus status() default INTERNAL_SERVER_ERROR;
} }
@Controller @RestController
@ResponseStatus(I_AM_A_TEAPOT)
private static class StatusController { private static class StatusController {
@RequestMapping("/teaPot")
void teaPot() {
}
@RequestMapping("/created") @RequestMapping("/created")
@ResponseStatus(CREATED) @ResponseStatus(CREATED)
public @ResponseBody void created(){ void created() {
} }
@Get(path = "/createdWithComposedAnnotation", status = CREATED) @Get(path = "/createdWithComposedAnnotation", status = CREATED)
public @ResponseBody void createdWithComposedAnnotation() { void createdWithComposedAnnotation() {
} }
@RequestMapping("/badRequest") @RequestMapping("/badRequest")
@ResponseStatus(code = BAD_REQUEST, reason = "Expired token") @ResponseStatus(code = BAD_REQUEST, reason = "Expired token")
public @ResponseBody void badRequest(){ void badRequest() {
} }
@RequestMapping("/notImplemented") @RequestMapping("/notImplemented")
@ResponseStatus(NOT_IMPLEMENTED) @ResponseStatus(NOT_IMPLEMENTED)
public @ResponseBody void notImplemented(){ void notImplemented() {
}
@RequestMapping("/throwsException")
@ResponseStatus(NOT_IMPLEMENTED)
void throwsException() {
throw new IllegalStateException();
}
@ExceptionHandler
void exceptionHandler(IllegalStateException ex) {
} }
} }

View File

@ -79,6 +79,8 @@ public @interface ResponseStatus {
/** /**
* The <em>reason</em> to be used for the response. * The <em>reason</em> to be used for the response.
* <p>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) * @see javax.servlet.http.HttpServletResponse#sendError(int, String)
*/ */
String reason() default ""; String reason() default "";