Commit Graph

1339 Commits

Author SHA1 Message Date
Sam Brannen
3c2dfebf4e Polish soft assertion support for WebTestClient
See gh-26969
2021-08-23 19:09:34 +02:00
Michal Rowicki
25dca40413 Introduce soft assertions for WebTestClient
It happens very often that WebTestClient is used in heavyweight
integration tests, and it's a hindrance to developer productivity to
fix one failed assertion after another. Soft assertions help a lot by
checking all conditions at once even if one of them fails.

This commit introduces a new expectAllSoftly(..) method in
WebTestClient to address this issue.

client.get().uri("/hello")
	.exchange()
	.expectAllSoftly(
		spec -> spec.expectStatus().isOk(),
		spec -> spec.expectBody(String.class).isEqualTo("Hello, World")
	);

Closes gh-26969
2021-08-23 19:09:23 +02:00
Sam Brannen
dd9b99e13d Introduce ResultActions.andExpectAll() for soft assertions in MockMvc
Closes gh-26917
2021-08-23 15:27:07 +02:00
Sam Brannen
cd078eaad8 Use ExceptionCollector for soft assertions in MockMvc
See gh-26917
2021-08-23 15:22:54 +02:00
Sam Brannen
5f47d3be22 Polish soft assertions for MockMvc
See gh-26917
2021-08-23 15:22:44 +02:00
Michal Rowicki
35bec8102b Introduce soft assertions for MockMvc
It happens very often that MockMvc is used in heavyweight integration
tests. It's no use to waste time to check if another condition has been
fixed or not. Soft assertions help a lot by checking all conditions at
once even if one of them fails.

See gh-26917

Co-authored-by: Sach Nguyen <sachnbbkhn@gmail.com>
2021-08-23 15:22:35 +02:00
Sam Brannen
4c153b80ee Make ExceptionCollector.Executable public
See gh-27316
2021-08-23 11:57:54 +02:00
Sam Brannen
81a6ba42a3 Introduce ExceptionCollector testing utility
This commit introduces a new ExceptionCollector testing utility in order
to support "soft assertion" use cases.

Closes gh-27316
2021-08-23 11:44:25 +02:00
Sam Brannen
8a7c4fc10d Support HtmlFileInput.setData() with HtmlUnit and MockMvc
Prior to this commit, if the user tested file upload support with
HtmlUnit and MockMvc by invoking HtmlFileInput.setData() instead of
HtmlFileInput.setFiles(), the in-memory file data was simply ignored.

This commit addresses this issue by creating a MockPart from the
in-memory data in HtmlUnitRequestBuilder.

Closes gh-27199
2021-08-22 17:44:14 +02:00
Sam Brannen
7da7a976e6 Document when prepareTestInstance() is invoked by the SpringMethodRule
Closes gh-27305
2021-08-22 15:56:58 +02:00
Sam Brannen
bd1f5bd9fc Support Charset for character encoding in MockMvc
To improve the developer experience and avoid the use of String
literals, this commit provides overloaded support via Charset for
character encoding in MockHttpServletRequestBuilder and
ContentResultMatchers.

Closes gh-27231
2021-07-30 15:24:47 +02:00
Sam Brannen
0f421f9f86 Support default character encoding for response in MockMvc
Commit e4b9b1fadb introduced support for setting the default character
encoding in MockHttpServletResponse.

This commit introduces support for configuring the default character
encoding in the underlying MockHttpServletResponse used in MockMvc.

Closes gh-27230
2021-07-30 14:42:45 +02:00
Sam Brannen
41fa199178 Polish PrintingResultHandler 2021-07-29 19:43:54 +02:00
Sam Brannen
881fa889fc Apply global ResultHandlers before ResultMatchers in MockMvc
Prior to this commit, MockMvc applied global ResultMatchers before
global ResultHandlers. This lead to unexpected scenarios where a
failing matcher would prevent a handler from being applied.

One concrete use case is `alwaysDo(print(System.err))` which should
print out MockMvc results for debugging purposes. However, if MockMvc is
configured with something like `alwaysExpect(content().string("?"))`
and the expectation fails, the user will never see the expected debug
output to help diagnose the problem.

This commit addresses this issue by applying global ResultHandlers
before ResultMatchers in MockMvc.

Closes gh-27225
2021-07-29 19:18:18 +02:00
Sam Brannen
e4b9b1fadb Introduce setDefaultCharacterEncoding() in MockHttpServletResponse
Prior to this commit, it was possible to set the character encoding
in MockHttpServletResponse via setCharacterEncoding() or
setContentType(); however, those methods append "charset=..." to the
Content-Type header which may not be an acceptable side effect.

This commit addresses this shortcoming by introducing a new
setDefaultCharacterEncoding() in MockHttpServletResponse which allows
one to override the previously hard coded value of "ISO-8859-1". In
addition, setDefaultCharacterEncoding() does not modify the Content-Type
header.

The reset() method has also been updated to reset the character encoding
to the configured default character encoding.

Closes gh-27214
2021-07-29 16:02:58 +02:00
Sam Brannen
5b3f11c543 Add @Nullable to setLocale in MockHttpServletResponse
See gh-26493
2021-07-29 14:47:31 +02:00
Sam Brannen
96ee8a3bc7 Ensure characterEncoding in MockHttpServletResponse is non-null
Closes gh-27219
2021-07-29 14:40:01 +02:00
Sam Brannen
403e04c0b4 Polish MockHttpServletResponse 2021-07-28 11:27:56 +02:00
Juergen Hoeller
acb2aec3dd Compatibility with HtmlUnit 2.51
Includes upgrade to Tomcat 9.0.50, Jetty 9.4.43, Jackson 2.12.4.

Closes gh-27147
2021-07-09 13:22:34 +02:00
Sam Brannen
a2ef6badc4 Use StringBuilder.append(char) where possible
To slightly improve performance, this commit switches to
StringBuilder.append(char) instead of StringBuilder.append(String)
whenever we append a single character to a StringBuilder.

Closes gh-27098
2021-06-25 10:44:28 +02:00
Rossen Stoyanchev
cc2b980e5c Update MockMvc default for suffixPattern matching
Closes gh-27030
2021-06-08 17:41:04 +01:00
Juergen Hoeller
5f5cd8a7c4 Log resource path resolution failure at debug level (instead of warn)
Closes gh-26828
2021-05-11 15:46:21 +02:00
Sam Brannen
d79e33b5a0 Handle empty file input in HtmlUnitRequestBuilder
This commit revises the fix submitted in 959e6d1745 by ensuring that
empty file input is converted to a MockPart with the supplied name, an
empty filename, "application/octet-stream" as the content type, and
empty content.

This aligns with the behavior of Servlet containers, as tested with the
interaction between Firefox and a standard Servlet running in a Jetty
Servlet container.

Closes gh-26799
2021-05-07 16:00:09 +02:00
Sam Brannen
959e6d1745 Handle empty file input in HtmlUnitRequestBuilder
Prior to this commit, when using HtmlUnit with empty file input,
MockMvc's HtmlUnitRequestBuilder would throw a NullPointerException
when attempting to create a MockPart based on the null File.

This commit ensures that empty file input is converted to a MockPart
with a valid name but with a null filename, a null content type, and
empty content.

Closes gh-26799
2021-05-05 18:11:15 +02:00
Sam Brannen
e4f753e3e3 Honor class-level @DirtiesContext if test class is disabled via SpEL
Prior to this commit, if a test class annotated with @DirtiesContext
and @EnabledIf/@DisabledIf with `loadContext = true` was disabled due
to the evaluated SpEL expression, the ApplicationContext would not be
marked as dirty and closed.

The reason is that @EnabledIf/@DisabledIf are implemented via JUnit
Jupiter's ExecutionCondition extension API which results in the entire
test class (as well as any associated extension callbacks) being
skipped if the condition evaluates to `disabled`. This effectively
prevents any of Spring's TestExecutionListener APIs from being invoked.
Consequently, the DirtiesContextTestExecutionListener does not get a
chance to honor the class-level @DirtiesContext declaration.

This commit fixes this by implementing part of the logic of
DirtiesContextTestExecutionListener in
AbstractExpressionEvaluatingCondition (i.e., the base class for
@EnabledIf/@DisabledIf support). Specifically, if the test class for an
eagerly loaded ApplicationContext is disabled,
AbstractExpressionEvaluatingCondition will now mark the test
ApplicationContext as dirty if the test class is annotated with
@DirtiesContext.

Closes gh-26694
2021-03-18 13:51:32 +01:00
Juergen Hoeller
4f14291e2f Add since tag
See gh-19647
2021-03-15 18:00:54 +01:00
Rossen Stoyanchev
c6b271f1b6 Support global Consumer<ExchangeResult> in WebTestClient
Closes gh-26662
2021-03-15 09:56:17 +00:00
Juergen Hoeller
c1b1940dd2 Polishing 2021-03-12 11:02:35 +01:00
Juergen Hoeller
97b3aa4b13 Polishing 2021-03-12 00:14:04 +01:00
Michal Stehlik
79b5710386 StatusAssertion value methods fail when used with custom status code 2021-03-11 15:57:32 +01:00
Johnny Lim
cf4e77907f Fix MockHttpServletRequest reference in Javadoc
Closes gh-26592
2021-02-23 10:43:38 +01:00
Rossen Stoyanchev
274db2f7a9 Undo HttpServletMapping support in MockHttpServletRequest
Closes gh-26555
2021-02-19 12:07:05 +00:00
Sam Brannen
49ccd7ad9c Polish MockHttpServletResponseTests
See gh-26558
2021-02-17 14:32:39 +01:00
Koos Gadellaa
40661d62c1 Support cookie w/ only Expires attribute in MockHttpServletResponse
Prior to this commit, MockHttpServletResponse only included the Expires
attribute in the generated Cookie header if the Max-Age attribute had
also been set.

This commit supports including the Expires attribute in the generated
Cookie Header even when the Max-Age attribute has not been set.

Closes gh-26558
2021-02-17 14:32:39 +01:00
Sam Brannen
e17ca9a4e9 Implement toString() in MockCookie 2021-02-17 14:32:38 +01:00
Juergen Hoeller
ca8261cbf8 Polishing 2021-02-15 17:18:01 +01:00
Juergen Hoeller
df977a2fd2 Nullability refinements and related polishing 2021-02-14 17:57:32 +01:00
Rossen Stoyanchev
c52526ad42 Fix in MockMultipartHttpServletRequest#getMultipartHeaders
Previously this method returned headers only when a Content-Type part header
was present. Now it is guaranteed to return headers (possibly empty) as long
as there is a MultipartFile or Part with the given name.

Closes gh-26501
2021-02-03 21:55:42 +00:00
Sam Brannen
1a3ff83157 Remove obsolete code in HeaderValueHolder 2021-02-02 11:28:32 +01:00
Sam Brannen
c19b2851f1 Ignore null Locale in MockHttpServletResponse
Prior to this commit, calls to setLocale() MockHttpServletResponse
would result in a NullPointerException if the supplied Locale was null.

Although the Javadoc for setLocale(Locale) and addHeader(String, String)
in javax.servlet.ServletResponse does not specify how a null
Locale should be handled, both Tomcat and Jetty simply ignore a null
value.

This commit therefore updates MockHttpServletResponse to silently
ignore a null Locale passed to setLocale().

Closes gh-26493
2021-02-02 11:18:34 +01:00
Sam Brannen
3b4a3431d4 Ignore null header value in MockHttpServletResponse
Prior to this commit, calls to setHeader() and addHeader() in
MockHttpServletResponse would result in an IllegalArgumentException or
NullPointerException if the supplied header value was null.

Although the Javadoc for setHeader(String, String) and
addHeader(String, String) in javax.servlet.http.HttpServletResponse
does not specify how a null header value should be handled, both Tomcat
and Jetty simply ignore a null value. Furthermore,
org.springframework.http.HttpHeaders.add(String, String) declares the
headerValue parameter as @Nullable.

This commit therefore updates MockHttpServletResponse to silently
ignore null header values passed to setHeader() and addHeader().

Closes gh-26488
2021-02-02 11:18:34 +01:00
Rossen Stoyanchev
f22e2ac578 Add HttpServletMapping support to MockHttpServletRequest
See gh-26428
2021-01-26 17:30:16 +00:00
Sam Brannen
4a7a2258f9 Unwrap proxied DataSources in SqlScriptsTestExecutionListener
Prior to this commit, if the DataSource in the
DataSourceFromTransactionManager was wrapped in a proxy implementing
InfrastructureProxy, SqlScriptsTestExecutionListener would throw an
exception stating that the DataSource in the ApplicationContext and the
DataSource in the DataSourceFromTransactionManager were not the same.

This commit unwraps both data sources and compares the underlying
target instances to check for equality.

In addition, this commit makes the unwrapResourceIfNecessary() method in
TransactionSynchronizationUtils public.

Closes gh-26422
2021-01-22 18:22:00 +01:00
Rossen Stoyanchev
584dabbb39 Add all non-file parts as request parameters
Closes gh-26400
2021-01-19 20:49:59 +00:00
Rossen Stoyanchev
35225e5794 Add verify(Duration) to MockRestServiceServer
Closes gh-22618
2021-01-13 17:50:01 +00:00
Rossen Stoyanchev
a1cf6bbc37 Avoid wrapping of AssertionError in ExchangeResult
Closes gh-26303
2021-01-06 21:56:14 +00:00
Rossen Stoyanchev
fb2e53276c Assert WebFlux present for WebTestClient
Closes gh-26308
2021-01-06 21:56:14 +00:00
Sam Brannen
1565f4b83e Introduce ApplicationEvents to assert events published during tests
This commit introduces a new feature in the Spring TestContext
Framework (TCF) that provides support for recording application events
published in the ApplicationContext so that assertions can be performed
against those events within tests. All events published during the
execution of a single test are made available via the ApplicationEvents
API which allows one to process the events as a java.util.Stream.

The following example demonstrates usage of this new feature.

@SpringJUnitConfig(/* ... */)
@RecordApplicationEvents
class OrderServiceTests {

    @Autowired
    OrderService orderService;

    @Autowired
    ApplicationEvents events;

    @Test
    void submitOrder() {
        // Invoke method in OrderService that publishes an event
        orderService.submitOrder(new Order(/* ... */));
        // Verify that an OrderSubmitted event was published
        int numEvents = events.stream(OrderSubmitted.class).count();
        assertThat(numEvents).isEqualTo(1);
    }
}

To enable the feature, a test class must be annotated or meta-annotated
with @RecordApplicationEvents. Behind the scenes, a new
ApplicationEventsTestExecutionListener manages the registration of
ApplicationEvents for the current thread at various points within the
test execution lifecycle and makes the current instance of
ApplicationEvents available to tests via an @Autowired field in the
test class. The latter is made possible by a custom ObjectFactory that
is registered as a "resolvable dependency". Thanks to the magic of
ObjectFactoryDelegatingInvocationHandler in the spring-beans module,
the ApplicationEvents instance injected into test classes is
effectively a scoped-proxy that always accesses the ApplicationEvents
managed for the current test.

The current ApplicationEvents instance is stored in a ThreadLocal
variable which is made available in the ApplicationEventsHolder.
Although this class is public, it is only intended for use within the
TCF or in the implementation of third-party extensions.

ApplicationEventsApplicationListener is responsible for listening to
all application events and recording them in the current
ApplicationEvents instance. A single
ApplicationEventsApplicationListener is registered with the test's
ApplicationContext by the ApplicationEventsTestExecutionListener.

The SpringExtension has also been updated to support parameters of type
ApplicationEvents via the JUnit Jupiter ParameterResolver extension
API. This allows JUnit Jupiter based tests to receive access to the
current ApplicationEvents via test and lifecycle method parameters as
an alternative to @Autowired fields in the test class.

Closes gh-25616
2020-12-20 23:46:19 +01:00
Juergen Hoeller
fbd2ffdd23 Consistent declarations and assertions in MockMultipartFile
See gh-26261
2020-12-16 22:27:33 +01:00
Sam Brannen
b3a47c76f8 Introduce TestContextAnnotationUtils.hasAnnotation() 2020-12-15 22:48:33 +01:00