Skip to content

Commit bcecce7

Browse files
committed
Add shortcuts for frequently used assertions
See gh-32712
1 parent c8967de commit bcecce7

File tree

4 files changed

+157
-31
lines changed

4 files changed

+157
-31
lines changed

spring-test/src/main/java/org/springframework/test/web/servlet/assertj/AbstractHttpServletResponseAssert.java

Lines changed: 97 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@
2828
import org.springframework.http.HttpHeaders;
2929
import org.springframework.http.HttpStatus;
3030
import org.springframework.http.HttpStatus.Series;
31+
import org.springframework.http.MediaType;
3132
import org.springframework.test.http.HttpHeadersAssert;
33+
import org.springframework.test.http.MediaTypeAssert;
3234
import org.springframework.util.LinkedMultiValueMap;
3335
import org.springframework.util.MultiValueMap;
3436
import org.springframework.util.function.SingletonSupplier;
@@ -48,15 +50,24 @@
4850
public abstract class AbstractHttpServletResponseAssert<R extends HttpServletResponse, SELF extends AbstractHttpServletResponseAssert<R, SELF, ACTUAL>, ACTUAL>
4951
extends AbstractObjectAssert<SELF, ACTUAL> {
5052

51-
private final Supplier<AbstractIntegerAssert<?>> statusAssert;
53+
private final Supplier<MediaTypeAssert> contentTypeAssertSupplier;
5254

5355
private final Supplier<HttpHeadersAssert> headersAssertSupplier;
5456

57+
private final Supplier<AbstractIntegerAssert<?>> statusAssert;
58+
5559

5660
protected AbstractHttpServletResponseAssert(ACTUAL actual, Class<?> selfType) {
5761
super(actual, selfType);
58-
this.statusAssert = SingletonSupplier.of(() -> Assertions.assertThat(getResponse().getStatus()).as("HTTP status code"));
62+
this.contentTypeAssertSupplier = SingletonSupplier.of(() -> new MediaTypeAssert(getResponse().getContentType()));
5963
this.headersAssertSupplier = SingletonSupplier.of(() -> new HttpHeadersAssert(getHttpHeaders(getResponse())));
64+
this.statusAssert = SingletonSupplier.of(() -> Assertions.assertThat(getResponse().getStatus()).as("HTTP status code"));
65+
}
66+
67+
private static HttpHeaders getHttpHeaders(HttpServletResponse response) {
68+
MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
69+
response.getHeaderNames().forEach(name -> headers.put(name, new ArrayList<>(response.getHeaders(name))));
70+
return new HttpHeaders(headers);
6071
}
6172

6273
/**
@@ -67,6 +78,14 @@ protected AbstractHttpServletResponseAssert(ACTUAL actual, Class<?> selfType) {
6778
*/
6879
protected abstract R getResponse();
6980

81+
/**
82+
* Return a new {@linkplain MediaTypeAssert assertion} object that uses the
83+
* response's {@linkplain MediaType content type} as the object to test.
84+
*/
85+
public MediaTypeAssert contentType() {
86+
return this.contentTypeAssertSupplier.get();
87+
}
88+
7089
/**
7190
* Return a new {@linkplain HttpHeadersAssert assertion} object that uses
7291
* {@link HttpHeaders} as the object to test. The returned assertion
@@ -84,6 +103,82 @@ public HttpHeadersAssert headers() {
84103
return this.headersAssertSupplier.get();
85104
}
86105

106+
// Content-type shortcuts
107+
108+
/**
109+
* Verify that the response's {@code Content-Type} is equal to the given value.
110+
* @param contentType the expected content type
111+
*/
112+
public SELF hasContentType(MediaType contentType) {
113+
contentType().isEqualTo(contentType);
114+
return this.myself;
115+
}
116+
117+
/**
118+
* Verify that the response's {@code Content-Type} is equal to the given
119+
* string representation.
120+
* @param contentType the expected content type
121+
*/
122+
public SELF hasContentType(String contentType) {
123+
contentType().isEqualTo(contentType);
124+
return this.myself;
125+
}
126+
127+
/**
128+
* Verify that the response's {@code Content-Type} is
129+
* {@linkplain MediaType#isCompatibleWith(MediaType) compatible} with the
130+
* given value.
131+
* @param contentType the expected compatible content type
132+
*/
133+
public SELF hasContentTypeCompatibleWith(MediaType contentType) {
134+
contentType().isCompatibleWith(contentType);
135+
return this.myself;
136+
}
137+
138+
/**
139+
* Verify that the response's {@code Content-Type} is
140+
* {@linkplain MediaType#isCompatibleWith(MediaType) compatible} with the
141+
* given string representation.
142+
* @param contentType the expected compatible content type
143+
*/
144+
public SELF hasContentTypeCompatibleWith(String contentType) {
145+
contentType().isCompatibleWith(contentType);
146+
return this.myself;
147+
}
148+
149+
// Headers shortcuts
150+
151+
/**
152+
* Verify that the response contains a header with the given {@code name}.
153+
* @param name the name of an expected HTTP header
154+
*/
155+
public SELF containsHeader(String name) {
156+
headers().containsHeader(name);
157+
return this.myself;
158+
}
159+
160+
/**
161+
* Verify that the response does not contain a header with the given {@code name}.
162+
* @param name the name of an HTTP header that should not be present
163+
*/
164+
public SELF doesNotContainHeader(String name) {
165+
headers().doesNotContainHeader(name);
166+
return this.myself;
167+
}
168+
169+
/**
170+
* Verify that the response contains a header with the given {@code name}
171+
* and primary {@code value}.
172+
* @param name the name of an expected HTTP header
173+
* @param value the expected value of the header
174+
*/
175+
public SELF hasHeader(String name, String value) {
176+
headers().hasValue(name, value);
177+
return this.myself;
178+
}
179+
180+
// Status
181+
87182
/**
88183
* Verify that the HTTP status is equal to the specified status code.
89184
* @param status the expected HTTP status code
@@ -159,10 +254,4 @@ private AbstractIntegerAssert<?> status() {
159254
return this.statusAssert.get();
160255
}
161256

162-
private static HttpHeaders getHttpHeaders(HttpServletResponse response) {
163-
MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
164-
response.getHeaderNames().forEach(name -> headers.put(name, new ArrayList<>(response.getHeaders(name))));
165-
return new HttpHeaders(headers);
166-
}
167-
168257
}

spring-test/src/main/java/org/springframework/test/web/servlet/assertj/MvcTestResultAssert.java

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,10 @@
3030
import org.assertj.core.error.BasicErrorMessageFactory;
3131
import org.assertj.core.internal.Failures;
3232

33-
import org.springframework.http.MediaType;
3433
import org.springframework.http.converter.GenericHttpMessageConverter;
3534
import org.springframework.lang.Nullable;
3635
import org.springframework.mock.web.MockHttpServletRequest;
3736
import org.springframework.mock.web.MockHttpServletResponse;
38-
import org.springframework.test.http.MediaTypeAssert;
3937
import org.springframework.test.web.servlet.MvcResult;
4038
import org.springframework.test.web.servlet.ResultHandler;
4139
import org.springframework.test.web.servlet.ResultMatcher;
@@ -87,14 +85,6 @@ public CookieMapAssert cookies() {
8785
return new CookieMapAssert(getMvcResult().getResponse().getCookies());
8886
}
8987

90-
/**
91-
* Return a new {@linkplain MediaTypeAssert assertion} object that uses the
92-
* response's {@linkplain MediaType content type} as the object to test.
93-
*/
94-
public MediaTypeAssert contentType() {
95-
return new MediaTypeAssert(getMvcResult().getResponse().getContentType());
96-
}
97-
9888
/**
9989
* Return a new {@linkplain HandlerResultAssert assertion} object that uses
10090
* the handler as the object to test. For a method invocation on a

spring-test/src/test/java/org/springframework/test/web/servlet/assertj/AbstractHttpServletResponseAssertTests.java

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.junit.jupiter.api.Test;
2424

2525
import org.springframework.http.HttpStatus;
26+
import org.springframework.http.MediaType;
2627
import org.springframework.mock.web.MockHttpServletResponse;
2728

2829
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
@@ -37,20 +38,76 @@ class AbstractHttpServletResponseAssertTests {
3738
@Nested
3839
class HeadersTests {
3940

41+
@Test
42+
void containsHeader() {
43+
MockHttpServletResponse response = createResponse(Map.of("n1", "v1", "n2", "v2", "n3", "v3"));
44+
assertThat(response).containsHeader("n1");
45+
}
46+
47+
@Test
48+
void doesNotContainHeader() {
49+
MockHttpServletResponse response = createResponse(Map.of("n1", "v1", "n2", "v2", "n3", "v3"));
50+
assertThat(response).doesNotContainHeader("n4");
51+
}
52+
53+
@Test
54+
void hasHeader() {
55+
MockHttpServletResponse response = createResponse(Map.of("n1", "v1", "n2", "v2", "n3", "v3"));
56+
assertThat(response).hasHeader("n1", "v1");
57+
}
58+
4059
@Test
4160
void headersAreMatching() {
4261
MockHttpServletResponse response = createResponse(Map.of("n1", "v1", "n2", "v2", "n3", "v3"));
4362
assertThat(response).headers().containsHeaders("n1", "n2", "n3");
4463
}
4564

46-
4765
private MockHttpServletResponse createResponse(Map<String, String> headers) {
4866
MockHttpServletResponse response = new MockHttpServletResponse();
4967
headers.forEach(response::addHeader);
5068
return response;
5169
}
5270
}
5371

72+
@Nested
73+
class ContentTypeTests {
74+
75+
@Test
76+
void contentType() {
77+
MockHttpServletResponse response = createResponse("text/plain");
78+
assertThat(response).hasContentType(MediaType.TEXT_PLAIN);
79+
}
80+
81+
@Test
82+
void contentTypeAndRepresentation() {
83+
MockHttpServletResponse response = createResponse("text/plain");
84+
assertThat(response).hasContentType("text/plain");
85+
}
86+
87+
@Test
88+
void contentTypeCompatibleWith() {
89+
MockHttpServletResponse response = createResponse("application/json;charset=UTF-8");
90+
assertThat(response).hasContentTypeCompatibleWith(MediaType.APPLICATION_JSON);
91+
}
92+
93+
@Test
94+
void contentTypeCompatibleWithAndStringRepresentation() {
95+
MockHttpServletResponse response = createResponse("text/plain");
96+
assertThat(response).hasContentTypeCompatibleWith("text/*");
97+
}
98+
99+
@Test
100+
void contentTypeCanBeAsserted() {
101+
MockHttpServletResponse response = createResponse("text/plain");
102+
assertThat(response).contentType().isInstanceOf(MediaType.class).isCompatibleWith("text/*").isNotNull();
103+
}
104+
105+
private MockHttpServletResponse createResponse(String contentType) {
106+
MockHttpServletResponse response = new MockHttpServletResponse();
107+
response.setContentType(contentType);
108+
return response;
109+
}
110+
}
54111

55112
@Nested
56113
class StatusTests {

spring-test/src/test/java/org/springframework/test/web/servlet/assertj/MockMvcTesterIntegrationTests.java

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -138,16 +138,6 @@ public boolean preHandle(HttpServletRequest request, HttpServletResponse respons
138138
}
139139
}
140140

141-
@Nested
142-
class ContentTypeTests {
143-
144-
@Test
145-
void contentType() {
146-
assertThat(perform(get("/greet"))).contentType().isCompatibleWith("text/plain");
147-
}
148-
149-
}
150-
151141
@Nested
152142
class StatusTests {
153143

@@ -168,8 +158,8 @@ class HeadersTests {
168158

169159
@Test
170160
void shouldAssertHeader() {
171-
assertThat(perform(get("/greet"))).headers()
172-
.hasValue("Content-Type", "text/plain;charset=ISO-8859-1");
161+
assertThat(perform(get("/greet")))
162+
.hasHeader("Content-Type", "text/plain;charset=ISO-8859-1");
173163
}
174164

175165
@Test

0 commit comments

Comments
 (0)