Skip to content

Commit

Permalink
Add AssertJ support for MockMvc
Browse files Browse the repository at this point in the history
Closes gh-21178
  • Loading branch information
snicoll committed Mar 15, 2024
2 parents 214a54d + e7d7cb8 commit 4a74e1f
Show file tree
Hide file tree
Showing 56 changed files with 7,023 additions and 0 deletions.
1 change: 1 addition & 0 deletions spring-test/spring-test.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ dependencies {
optional("org.apache.groovy:groovy")
optional("org.apache.tomcat.embed:tomcat-embed-core")
optional("org.aspectj:aspectjweaver")
optional("org.assertj:assertj-core")
optional("org.hamcrest:hamcrest")
optional("org.htmlunit:htmlunit") {
exclude group: "commons-logging", module: "commons-logging"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/*
* Copyright 2002-2024 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.test.http;

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;

import org.assertj.core.api.AbstractMapAssert;
import org.assertj.core.api.Assertions;

import org.springframework.http.HttpHeaders;

/**
* AssertJ {@link org.assertj.core.api.Assert assertions} that can be applied to
* {@link HttpHeaders}.
*
* @author Stephane Nicoll
* @since 6.2
*/
public class HttpHeadersAssert extends AbstractMapAssert<HttpHeadersAssert, HttpHeaders, String, List<String>> {

private static final ZoneId GMT = ZoneId.of("GMT");


public HttpHeadersAssert(HttpHeaders actual) {
super(actual, HttpHeadersAssert.class);
as("HTTP headers");
}

/**
* Verify that the actual HTTP headers contain a header with the given
* {@code name}.
* @param name the name of an expected HTTP header
* @see #containsKey
*/
public HttpHeadersAssert containsHeader(String name) {
return containsKey(name);
}

/**
* Verify that the actual HTTP headers contain the headers with the given
* {@code names}.
* @param names the names of expected HTTP headers
* @see #containsKeys
*/
public HttpHeadersAssert containsHeaders(String... names) {
return containsKeys(names);
}

/**
* Verify that the actual HTTP headers do not contain a header with the
* given {@code name}.
* @param name the name of an HTTP header that should not be present
* @see #doesNotContainKey
*/
public HttpHeadersAssert doesNotContainsHeader(String name) {
return doesNotContainKey(name);
}

/**
* Verify that the actual HTTP headers do not contain any of the headers
* with the given {@code names}.
* @param names the names of HTTP headers that should not be present
* @see #doesNotContainKeys
*/
public HttpHeadersAssert doesNotContainsHeaders(String... names) {
return doesNotContainKeys(names);
}

/**
* Verify that the actual HTTP headers contain a header with the given
* {@code name} and {@link String} {@code value}.
* @param name the name of the cookie
* @param value the expected value of the header
*/
public HttpHeadersAssert hasValue(String name, String value) {
containsKey(name);
Assertions.assertThat(this.actual.getFirst(name))
.as("check primary value for HTTP header '%s'", name)
.isEqualTo(value);
return this.myself;
}

/**
* Verify that the actual HTTP headers contain a header with the given
* {@code name} and {@link Long} {@code value}.
* @param name the name of the cookie
* @param value the expected value of the header
*/
public HttpHeadersAssert hasValue(String name, long value) {
containsKey(name);
Assertions.assertThat(this.actual.getFirst(name))
.as("check primary long value for HTTP header '%s'", name)
.asLong().isEqualTo(value);
return this.myself;
}

/**
* Verify that the actual HTTP headers contain a header with the given
* {@code name} and {@link Instant} {@code value}.
* @param name the name of the cookie
* @param value the expected value of the header
*/
public HttpHeadersAssert hasValue(String name, Instant value) {
containsKey(name);
Assertions.assertThat(this.actual.getFirstZonedDateTime(name))
.as("check primary date value for HTTP header '%s'", name)
.isCloseTo(ZonedDateTime.ofInstant(value, GMT), Assertions.within(999, ChronoUnit.MILLIS));
return this.myself;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* Copyright 2002-2024 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.test.http;

import org.assertj.core.api.AbstractObjectAssert;
import org.assertj.core.api.Assertions;
import org.assertj.core.error.BasicErrorMessageFactory;
import org.assertj.core.internal.Failures;

import org.springframework.http.InvalidMediaTypeException;
import org.springframework.http.MediaType;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;

/**
* AssertJ {@link org.assertj.core.api.Assert assertions} that can be applied
* to a {@link MediaType}.
*
* @author Brian Clozel
* @author Stephane Nicoll
* @since 6.2
*/
public class MediaTypeAssert extends AbstractObjectAssert<MediaTypeAssert, MediaType> {

public MediaTypeAssert(@Nullable MediaType mediaType) {
super(mediaType, MediaTypeAssert.class);
as("Media type");
}

public MediaTypeAssert(@Nullable String actual) {
this(StringUtils.hasText(actual) ? MediaType.parseMediaType(actual) : null);
}

/**
* Verify that the actual media type is equal to the given string
* representation.
* @param expected the expected media type
*/
public MediaTypeAssert isEqualTo(String expected) {
return isEqualTo(parseMediaType(expected));
}

/**
* Verify that the actual media type is
* {@linkplain MediaType#isCompatibleWith(MediaType) compatible} with the
* given one. Example: <pre><code class='java'>
* // Check that actual is compatible with "application/json"
* assertThat(mediaType).isCompatibleWith(MediaType.APPLICATION_JSON);
* </code></pre>
* @param mediaType the media type with which to compare
*/
public MediaTypeAssert isCompatibleWith(MediaType mediaType) {
Assertions.assertThat(this.actual)
.withFailMessage("Expecting null to be compatible with '%s'", mediaType).isNotNull();
Assertions.assertThat(mediaType)
.withFailMessage("Expecting '%s' to be compatible with null", this.actual).isNotNull();
Assertions.assertThat(this.actual.isCompatibleWith(mediaType))
.as("check media type '%s' is compatible with '%s'", this.actual.toString(), mediaType.toString())
.isTrue();
return this;
}

/**
* Verify that the actual media type is
* {@linkplain MediaType#isCompatibleWith(MediaType) compatible} with the
* given one. Example: <pre><code class='java'>
* // Check that actual is compatible with "text/plain"
* assertThat(mediaType).isCompatibleWith("text/plain");
* </code></pre>
* @param mediaType the media type with which to compare
*/
public MediaTypeAssert isCompatibleWith(String mediaType) {
return isCompatibleWith(parseMediaType(mediaType));
}


private MediaType parseMediaType(String value) {
try {
return MediaType.parseMediaType(value);
}
catch (InvalidMediaTypeException ex) {
throw Failures.instance().failure(this.info, new ShouldBeValidMediaType(value, ex.getMessage()));
}
}

private static final class ShouldBeValidMediaType extends BasicErrorMessageFactory {

private ShouldBeValidMediaType(String mediaType, String errorMessage) {
super("%nExpecting:%n %s%nTo be a valid media type but got:%n %s%n", mediaType, errorMessage);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* Test support for HTTP concepts.
*/
@NonNullApi
@NonNullFields
package org.springframework.test.http;

import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;
Loading

0 comments on commit 4a74e1f

Please sign in to comment.