Skip to content

Commit caf84ff

Browse files
simonbaslesnicoll
andcommitted
Revisit HttpHeadersAssert after HttpHeaders API changes
- add various assertions to HttpHeadersAssert - improve assertion test coverage - remove niche size assertions Closes gh-34168 Co-authored-by: Stephane Nicoll <[email protected]>
1 parent 448d6c6 commit caf84ff

File tree

3 files changed

+354
-87
lines changed

3 files changed

+354
-87
lines changed

spring-test/src/main/java/org/springframework/test/http/HttpHeadersAssert.java

Lines changed: 76 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,12 @@
2323
import java.util.Arrays;
2424
import java.util.Collection;
2525
import java.util.List;
26+
import java.util.function.Consumer;
2627

2728
import org.assertj.core.api.AbstractCollectionAssert;
2829
import org.assertj.core.api.AbstractObjectAssert;
2930
import org.assertj.core.api.Assertions;
3031
import org.assertj.core.api.ObjectAssert;
31-
import org.assertj.core.presentation.Representation;
32-
import org.assertj.core.presentation.StandardRepresentation;
3332

3433
import org.springframework.http.HttpHeaders;
3534

@@ -38,6 +37,7 @@
3837
* {@link HttpHeaders}.
3938
*
4039
* @author Stephane Nicoll
40+
* @author Simon Baslé
4141
* @since 6.2
4242
*/
4343
public class HttpHeadersAssert extends AbstractObjectAssert<HttpHeadersAssert, HttpHeaders> {
@@ -50,15 +50,6 @@ public class HttpHeadersAssert extends AbstractObjectAssert<HttpHeadersAssert, H
5050
public HttpHeadersAssert(HttpHeaders actual) {
5151
super(actual, HttpHeadersAssert.class);
5252
as("HTTP headers");
53-
withRepresentation(new Representation() {
54-
@Override
55-
public String toStringOf(Object object) {
56-
if (object instanceof HttpHeaders headers) {
57-
return headers.toString();
58-
}
59-
return StandardRepresentation.STANDARD_REPRESENTATION.toStringOf(object);
60-
}
61-
});
6253
this.namesAssert = Assertions.assertThat(actual.headerNames())
6354
.as("HTTP header names");
6455
}
@@ -127,7 +118,23 @@ public HttpHeadersAssert doesNotContainHeaders(String... names) {
127118

128119
/**
129120
* Verify that the actual HTTP headers contain a header with the given
130-
* {@code name} and {@link String} {@code value}.
121+
* {@code name} that satisfies the given {@code valueRequirements}.
122+
* @param name the name of an HTTP header that should not be present
123+
* @param valueRequirements the group of assertions to run against the
124+
* values of the header with the given name
125+
*/
126+
@SuppressWarnings("unchecked")
127+
public HttpHeadersAssert hasHeaderSatisfying(String name, Consumer<List<String>> valueRequirements) {
128+
containsHeader(name);
129+
Assertions.assertThat(this.actual.get(name))
130+
.as("check primary value for HTTP header '%s'", name)
131+
.satisfies(values -> valueRequirements.accept((List<String>) values));
132+
return this.myself;
133+
}
134+
135+
/**
136+
* Verify that the actual HTTP headers contain a header with the given
137+
* {@code name} and {@link String} primary {@code value}.
131138
* @param name the name of the cookie
132139
* @param value the expected value of the header
133140
*/
@@ -141,7 +148,7 @@ public HttpHeadersAssert hasValue(String name, String value) {
141148

142149
/**
143150
* Verify that the actual HTTP headers contain a header with the given
144-
* {@code name} and {@link Long} {@code value}.
151+
* {@code name} and {@link Long} primary {@code value}.
145152
* @param name the name of the cookie
146153
* @param value the expected value of the header
147154
*/
@@ -155,7 +162,7 @@ public HttpHeadersAssert hasValue(String name, long value) {
155162

156163
/**
157164
* Verify that the actual HTTP headers contain a header with the given
158-
* {@code name} and {@link Instant} {@code value}.
165+
* {@code name} and {@link Instant} primary {@code value}.
159166
* @param name the name of the cookie
160167
* @param value the expected value of the header
161168
*/
@@ -167,6 +174,46 @@ public HttpHeadersAssert hasValue(String name, Instant value) {
167174
return this.myself;
168175
}
169176

177+
/**
178+
* Verify that the actual HTTP headers contain a header with the given
179+
* {@code name} and {@link String} primary {@code value}.
180+
* <p>This assertion fails if the header has secondary values.
181+
* @param name the name of the cookie
182+
* @param value the expected only value of the header
183+
* @since 7.0
184+
*/
185+
public HttpHeadersAssert hasSingleValue(String name, String value) {
186+
doesNotHaveSecondaryValues(name);
187+
return hasValue(name, value);
188+
}
189+
190+
/**
191+
* Verify that the actual HTTP headers contain a header with the given
192+
* {@code name} and {@link Long} primary {@code value}.
193+
* <p>This assertion fails if the header has secondary values.
194+
* @param name the name of the cookie
195+
* @param value the expected value of the header
196+
* @since 7.0
197+
*/
198+
public HttpHeadersAssert hasSingleValue(String name, long value) {
199+
doesNotHaveSecondaryValues(name);
200+
return hasValue(name, value);
201+
}
202+
203+
/**
204+
* Verify that the actual HTTP headers contain a header with the given
205+
* {@code name} and {@link Instant} primary {@code value}.
206+
* <p>This assertion fails if the header has secondary values.
207+
* @param name the name of the cookie
208+
* @param value the expected value of the header
209+
* @since 7.0
210+
*/
211+
public HttpHeadersAssert hasSingleValue(String name, Instant value) {
212+
doesNotHaveSecondaryValues(name);
213+
return hasValue(name, value);
214+
}
215+
216+
170217
/**
171218
* Verify that the given header has a full list of values exactly equal to
172219
* the given list of values, and in the same order.
@@ -224,80 +271,13 @@ public HttpHeadersAssert isNotEmpty() {
224271
*/
225272
public HttpHeadersAssert hasSize(int expected) {
226273
this.namesAssert
227-
.as("check headers have size '%i'", expected)
274+
.as("check headers have size '%s'", expected)
228275
.hasSize(expected);
229276
return this.myself;
230277
}
231278

232279
/**
233-
* Verify that the number of headers present is strictly greater than the
234-
* given boundary, when considering header names in a case-insensitive
235-
* manner.
236-
* @param boundary the given value to compare actual header size to
237-
*/
238-
public HttpHeadersAssert hasSizeGreaterThan(int boundary) {
239-
this.namesAssert
240-
.as("check headers have size > '%i'", boundary)
241-
.hasSizeGreaterThan(boundary);
242-
return this.myself;
243-
}
244-
245-
/**
246-
* Verify that the number of headers present is greater or equal to the
247-
* given boundary, when considering header names in a case-insensitive
248-
* manner.
249-
* @param boundary the given value to compare actual header size to
250-
*/
251-
public HttpHeadersAssert hasSizeGreaterThanOrEqualTo(int boundary) {
252-
this.namesAssert
253-
.as("check headers have size >= '%i'", boundary)
254-
.hasSizeGreaterThanOrEqualTo(boundary);
255-
return this.myself;
256-
}
257-
258-
/**
259-
* Verify that the number of headers present is strictly less than the
260-
* given boundary, when considering header names in a case-insensitive
261-
* manner.
262-
* @param boundary the given value to compare actual header size to
263-
*/
264-
public HttpHeadersAssert hasSizeLessThan(int boundary) {
265-
this.namesAssert
266-
.as("check headers have size < '%i'", boundary)
267-
.hasSizeLessThan(boundary);
268-
return this.myself;
269-
}
270-
271-
/**
272-
* Verify that the number of headers present is less than or equal to the
273-
* given boundary, when considering header names in a case-insensitive
274-
* manner.
275-
* @param boundary the given value to compare actual header size to
276-
*/
277-
public HttpHeadersAssert hasSizeLessThanOrEqualTo(int boundary) {
278-
this.namesAssert
279-
.as("check headers have size <= '%i'", boundary)
280-
.hasSizeLessThanOrEqualTo(boundary);
281-
return this.myself;
282-
}
283-
284-
/**
285-
* Verify that the number of headers present is between the given boundaries
286-
* (inclusive), when considering header names in a case-insensitive manner.
287-
* @param lowerBoundary the lower boundary compared to which actual size
288-
* should be greater than or equal to
289-
* @param higherBoundary the higher boundary compared to which actual size
290-
* should be less than or equal to
291-
*/
292-
public HttpHeadersAssert hasSizeBetween(int lowerBoundary, int higherBoundary) {
293-
this.namesAssert
294-
.as("check headers have size between '%i' and '%i'", lowerBoundary, higherBoundary)
295-
.hasSizeBetween(lowerBoundary, higherBoundary);
296-
return this.myself;
297-
}
298-
299-
/**
300-
* Verify that the number actual headers is the same as in the given
280+
* Verify that the number of actual headers is the same as in the given
301281
* {@code HttpHeaders}.
302282
* @param other the {@code HttpHeaders} to compare size with
303283
* @since 7.0
@@ -308,4 +288,17 @@ public HttpHeadersAssert hasSameSizeAs(HttpHeaders other) {
308288
.hasSize(other.size());
309289
return this.myself;
310290
}
291+
292+
293+
private HttpHeadersAssert doesNotHaveSecondaryValues(String name) {
294+
containsHeader(name);
295+
List<String> values = this.actual.get(name);
296+
int size = (values != null) ? values.size() : 0;
297+
Assertions.assertThat(size)
298+
.withFailMessage("Expected HTTP header '%s' to be present " +
299+
"without secondary values, but found <%s> secondary values", name, size - 1)
300+
.isOne();
301+
return this.myself;
302+
}
303+
311304
}

0 commit comments

Comments
 (0)