Browse Source
This commit restructures the section on MockMvc so that the anchors are easier to read. The standard integration has moved to a Hamcrest Integration section at the same level as HtmlUnit Integration, and a new AssertJ Integration section has been created. Closes gh-32454pull/33085/head
54 changed files with 1432 additions and 272 deletions
@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
|
||||
[[mockmvc]] |
||||
= MockMvc |
||||
:page-section-summary-toc: 1 |
||||
|
||||
MockMvc provides support for testing Spring MVC applications. It performs full Spring MVC |
||||
request handling but via mock request and response objects instead of a running server. |
||||
|
||||
MockMvc can be used on its own to perform requests and verify responses responses using |
||||
Hamcrest, or through `MockMvcTester` that provides a fluent API using AssertJ. Finally, |
||||
it can also be used through the xref:testing/webtestclient.adoc[WebTestClient] where |
||||
MockMvc is plugged in as the server to handle requests with. The advantage of |
||||
`WebTestClient` is the option to work with higher level objects instead of raw data as |
||||
well as the ability to switch to full, end-to-end HTTP tests against a live server and |
||||
use the same test API. |
||||
|
||||
|
||||
@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
|
||||
[[mockmvc-tester]] |
||||
= AssertJ Integration |
||||
:page-section-summary-toc: 1 |
||||
|
||||
The AssertJ integration builds on top of plain `MockMvc` with several differences: |
||||
|
||||
* There is no need to use static imports as both the requests and assertions can be |
||||
crafted using a fluent API. |
||||
* Unresolved exceptions are handled consistently so that your tests do not need to |
||||
throw (or catch) `Exception`. |
||||
* By default, the result to assert is complete whether the processing is asynchronous |
||||
or not. In other words, there is no need for special handling for Async requests. |
||||
|
||||
`MockMvcTester` is the entry point for the AssertJ support. It allows to craft the |
||||
request and return a result that is AssertJ compatible so that it can be wrapped in |
||||
a standard `assertThat()` method. |
||||
@ -0,0 +1,49 @@
@@ -0,0 +1,49 @@
|
||||
[[mockmvc-tester-assertions]] |
||||
= Defining Expectations |
||||
|
||||
Assertions work the same way as any AssertJ assertions. The support provides dedicated |
||||
assert objects for the various pieces of the `MvcTestResult`, as shown in the following |
||||
example: |
||||
|
||||
include-code::./HotelControllerTests[tag=get,indent=0] |
||||
|
||||
If a request fails, the exchange does not throw the exception. Rather, you can assert |
||||
that the result of the exchange has failed: |
||||
|
||||
include-code::./HotelControllerTests[tag=failure,indent=0] |
||||
|
||||
The request could also fail unexpectedly, that is the exception thrown by the handler |
||||
has not been handled and is thrown as is. You can still use `.hasFailed()` and |
||||
`.failure()` but any attempt to access part of the result will throw an exception as |
||||
the exchange hasn't completed. |
||||
|
||||
[[mockmvc-tester-assertions-json]] |
||||
== JSON Support |
||||
|
||||
The AssertJ support for `MvcTestResult` provides JSON support via `bodyJson()`. |
||||
|
||||
If https://github.com/jayway/JsonPath[JSONPath] is available, you can apply an expression |
||||
on the JSON document. The returned value provides convenient methods to return a dedicated |
||||
assert object for the various supported JSON data types: |
||||
|
||||
include-code::./FamilyControllerTests[tag=extract-asmap,indent=0] |
||||
|
||||
You can also convert the raw content to any of your data types as long as the message |
||||
converter is configured properly: |
||||
|
||||
include-code::./FamilyControllerTests[tag=extract-convert,indent=0] |
||||
|
||||
Converting to a target `Class` provides a generic assert object. For more complex types, |
||||
you may want to use `AssertFactory` instead that returns a dedicated assert type, if |
||||
possible: |
||||
|
||||
include-code::./FamilyControllerTests[tag=extract-convert-assert-factory,indent=0] |
||||
|
||||
https://jsonassert.skyscreamer.org[JSONAssert] is also supported. The body of the |
||||
response can be matched against a `Resource` or a content. If the content ends with |
||||
`.json ` we look for a file matching that name on the classpath: |
||||
|
||||
include-code::./FamilyControllerTests[tag=assert-file,indent=0] |
||||
|
||||
If you prefer to use another library, you can provide an implementation of |
||||
{spring-framework-api}/test/json/JsonComparator.html[`JsonComparator`]. |
||||
@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
|
||||
[[mockmvc-tester-integration]] |
||||
= MockMvc integration |
||||
|
||||
If you want to use the AssertJ support but have invested in the original `MockMvc` |
||||
API, `MockMvcTester` offers several ways to integrate with it. |
||||
|
||||
If you have your own `RequestBuilder` implementation, you can trigger the processing |
||||
of the request using `perform`. The example below showcases how the query can be |
||||
crafted with the original API: |
||||
|
||||
include-code::./HotelControllerTests[tag=perform,indent=0] |
||||
|
||||
Similarly, if you have crafted custom matchers that you use with the `.andExpect` feature |
||||
of `MockMvc` you can use them via `.matches`. In the example below, we rewrite the |
||||
preceding example to assert the status with the `ResultMatcher` implementation that |
||||
`MockMvc` provides: |
||||
|
||||
include-code::./HotelControllerTests[tag=matches,indent=0] |
||||
|
||||
`MockMvc` also defines a `ResultHandler` contract that lets you execute arbitrary actions |
||||
on `MvcResult`. If you have implemented this contract you can invoke it using `.apply`. |
||||
|
||||
|
||||
@ -0,0 +1,83 @@
@@ -0,0 +1,83 @@
|
||||
[[mockmvc-tester-requests]] |
||||
= Performing Requests |
||||
|
||||
This section shows how to use `MockMvcTester` to perform requests and its integration |
||||
with AssertJ to verify responses. |
||||
|
||||
`MockMvcTester` provides a fluent API to compose the request that reuses the same |
||||
`MockHttpServletRequestBuilder` as the Hamcrest support, except that there is no need |
||||
to import a static method. The builder that is returned is AssertJ-aware so that |
||||
wrapping it in the regular `assertThat()` factory method triggers the exchange and |
||||
provides access to a dedicated Assert object for `MvcTestResult`. |
||||
|
||||
Here is a simple example that performs a `POST` on `/hotels/42` and configures the |
||||
request to specify an `Accept` header: |
||||
|
||||
include-code::./HotelControllerTests[tag=post,indent=0] |
||||
|
||||
AssertJ often consists of multiple `assertThat()` statements to validate the different |
||||
parts of the exchange. Rather than having a single statement as in the case above, you |
||||
can use `.exchange()` to return a `MvcTestResult` that can be used in multiple |
||||
`assertThat` statements: |
||||
|
||||
include-code::./HotelControllerTests[tag=post-exchange,indent=0] |
||||
|
||||
You can specify query parameters in URI template style, as the following example shows: |
||||
|
||||
include-code::./HotelControllerTests[tag=query-parameters,indent=0] |
||||
|
||||
You can also add Servlet request parameters that represent either query or form |
||||
parameters, as the following example shows: |
||||
|
||||
include-code::./HotelControllerTests[tag=parameters,indent=0] |
||||
|
||||
If application code relies on Servlet request parameters and does not check the query |
||||
string explicitly (as is most often the case), it does not matter which option you use. |
||||
Keep in mind, however, that query parameters provided with the URI template are decoded |
||||
while request parameters provided through the `param(...)` method are expected to already |
||||
be decoded. |
||||
|
||||
|
||||
[[mockmvc-tester-requests-async]] |
||||
== Async |
||||
|
||||
If the processing of the request is done asynchronously, `exchange()` waits for |
||||
the completion of the request so that the result to assert is effectively immutable. |
||||
The default timeout is 10 seconds but it can be controlled on a request-by-request |
||||
basis as shown in the following example: |
||||
|
||||
include-code::./AsyncControllerTests[tag=duration,indent=0] |
||||
|
||||
If you prefer to get the raw result and manage the lifecycle of the asynchronous |
||||
request yourself, use `asyncExchange` rather than `exchange`. |
||||
|
||||
[[mockmvc-tester-requests-multipart]] |
||||
== Multipart |
||||
|
||||
You can perform file upload requests that internally use |
||||
`MockMultipartHttpServletRequest` so that there is no actual parsing of a multipart |
||||
request. Rather, you have to set it up to be similar to the following example: |
||||
|
||||
include-code::./MultipartControllerTests[tag=snippet,indent=0] |
||||
|
||||
[[mockmvc-tester-requests-paths]] |
||||
== Using Servlet and Context Paths |
||||
|
||||
In most cases, it is preferable to leave the context path and the Servlet path out of the |
||||
request URI. If you must test with the full request URI, be sure to set the `contextPath` |
||||
and `servletPath` accordingly so that request mappings work, as the following example |
||||
shows: |
||||
|
||||
include-code::./HotelControllerTests[tag=context-servlet-paths,indent=0] |
||||
|
||||
In the preceding example, it would be cumbersome to set the `contextPath` and |
||||
`servletPath` with every performed request. Instead, you can set up default request |
||||
properties, as the following example shows: |
||||
|
||||
include-code::./HotelControllerTests[tag=default-customizations,indent=0] |
||||
|
||||
The preceding properties affect every request performed through the `mockMvc` instance. |
||||
If the same property is also specified on a given request, it overrides the default |
||||
value. That is why the HTTP method and URI in the default request do not matter, since |
||||
they must be specified on every request. |
||||
|
||||
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
[[mockmvc-tester-setup]] |
||||
= Configuring MockMvcTester |
||||
|
||||
`MockMvcTester` can be setup in one of two ways. One is to point directly to the |
||||
controllers you want to test and programmatically configure Spring MVC infrastructure. |
||||
The second is to point to Spring configuration with Spring MVC and controller |
||||
infrastructure in it. |
||||
|
||||
TIP: For a comparison of those two modes, check xref:testing/mockmvc/setup-options.adoc[Setup Options]. |
||||
|
||||
To set up `MockMvcTester` for testing a specific controller, use the following: |
||||
|
||||
include-code::./AccountControllerStandaloneTests[tag=snippet,indent=0] |
||||
|
||||
To set up `MockMvcTester` through Spring configuration, use the following: |
||||
|
||||
include-code::./AccountControllerIntegrationTests[tag=snippet,indent=0] |
||||
|
||||
`MockMvcTester` can convert the JSON response body, or the result of a JSONPath expression, |
||||
to one of your domain object as long as the relevant `HttpMessageConverter` is registered. |
||||
|
||||
If you use Jackson to serialize content to JSON, the following example registers the |
||||
converter: |
||||
|
||||
include-code::./converter/AccountControllerIntegrationTests[tag=snippet,indent=0] |
||||
|
||||
NOTE: The above assumes the converter has been registered as a Bean. |
||||
|
||||
Finally, if you have a `MockMvc` instance handy, you can create a `MockMvcTester` by |
||||
providing the `MockMvc` instance to use using the `create` factory method. |
||||
@ -0,0 +1,7 @@
@@ -0,0 +1,7 @@
|
||||
[[mockmvc-server]] |
||||
= Hamcrest Integration |
||||
:page-section-summary-toc: 1 |
||||
|
||||
Plain `MockMvc` provides an API to build the request using a builder-style approach |
||||
that can be initiated with static imports. Hamcrest is used to define expectations and |
||||
it provides many out-of-the-box options for common needs. |
||||
@ -1,4 +1,4 @@
@@ -1,4 +1,4 @@
|
||||
[[spring-mvc-test-async-requests]] |
||||
[[mockmvc-async-requests]] |
||||
= Async Requests |
||||
|
||||
This section shows how to use MockMvc on its own to test asynchronous request handling. |
||||
@ -1,4 +1,4 @@
@@ -1,4 +1,4 @@
|
||||
[[spring-mvc-test-server-defining-expectations]] |
||||
[[mockmvc-server-defining-expectations]] |
||||
= Defining Expectations |
||||
|
||||
You can define expectations by appending one or more `andExpect(..)` calls after |
||||
@ -1,4 +1,4 @@
@@ -1,4 +1,4 @@
|
||||
[[spring-mvc-test-server-filters]] |
||||
[[mockmvc-server-filters]] |
||||
= Filter Registrations |
||||
:page-section-summary-toc: 1 |
||||
|
||||
@ -1,4 +1,4 @@
@@ -1,4 +1,4 @@
|
||||
[[spring-mvc-test-server-performing-requests]] |
||||
[[mockmvc-server-performing-requests]] |
||||
= Performing Requests |
||||
|
||||
This section shows how to use MockMvc on its own to perform requests and verify responses. |
||||
@ -1,4 +1,4 @@
@@ -1,4 +1,4 @@
|
||||
[[spring-mvc-test-server-setup-steps]] |
||||
[[mockmvc-server-setup-steps]] |
||||
= Setup Features |
||||
|
||||
No matter which MockMvc builder you use, all `MockMvcBuilder` implementations provide |
||||
@ -0,0 +1,100 @@
@@ -0,0 +1,100 @@
|
||||
[[mockmvc-setup]] |
||||
= Configuring MockMvc |
||||
|
||||
MockMvc can be setup in one of two ways. One is to point directly to the controllers you |
||||
want to test and programmatically configure Spring MVC infrastructure. The second is to |
||||
point to Spring configuration with Spring MVC and controller infrastructure in it. |
||||
|
||||
TIP: For a comparison of those two modes, check xref:testing/mockmvc/setup-options.adoc[Setup Options]. |
||||
|
||||
To set up MockMvc for testing a specific controller, use the following: |
||||
|
||||
[tabs] |
||||
====== |
||||
Java:: |
||||
+ |
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
||||
---- |
||||
class MyWebTests { |
||||
|
||||
MockMvc mockMvc; |
||||
|
||||
@BeforeEach |
||||
void setup() { |
||||
this.mockMvc = MockMvcBuilders.standaloneSetup(new AccountController()).build(); |
||||
} |
||||
|
||||
// ... |
||||
|
||||
} |
||||
---- |
||||
|
||||
Kotlin:: |
||||
+ |
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
||||
---- |
||||
class MyWebTests { |
||||
|
||||
lateinit var mockMvc : MockMvc |
||||
|
||||
@BeforeEach |
||||
fun setup() { |
||||
mockMvc = MockMvcBuilders.standaloneSetup(AccountController()).build() |
||||
} |
||||
|
||||
// ... |
||||
|
||||
} |
||||
---- |
||||
====== |
||||
|
||||
Or you can also use this setup when testing through the |
||||
xref:testing/webtestclient.adoc#webtestclient-controller-config[WebTestClient] which delegates to the same builder |
||||
as shown above. |
||||
|
||||
To set up MockMvc through Spring configuration, use the following: |
||||
|
||||
[tabs] |
||||
====== |
||||
Java:: |
||||
+ |
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
||||
---- |
||||
@SpringJUnitWebConfig(locations = "my-servlet-context.xml") |
||||
class MyWebTests { |
||||
|
||||
MockMvc mockMvc; |
||||
|
||||
@BeforeEach |
||||
void setup(WebApplicationContext wac) { |
||||
this.mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); |
||||
} |
||||
|
||||
// ... |
||||
|
||||
} |
||||
---- |
||||
|
||||
Kotlin:: |
||||
+ |
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
||||
---- |
||||
@SpringJUnitWebConfig(locations = ["my-servlet-context.xml"]) |
||||
class MyWebTests { |
||||
|
||||
lateinit var mockMvc: MockMvc |
||||
|
||||
@BeforeEach |
||||
fun setup(wac: WebApplicationContext) { |
||||
mockMvc = MockMvcBuilders.webAppContextSetup(wac).build() |
||||
} |
||||
|
||||
// ... |
||||
|
||||
} |
||||
---- |
||||
====== |
||||
|
||||
Or you can also use this setup when testing through the |
||||
xref:testing/webtestclient.adoc#webtestclient-context-config[WebTestClient] which delegates to the same builder |
||||
as shown above. |
||||
@ -1,4 +1,4 @@
@@ -1,4 +1,4 @@
|
||||
[[spring-mvc-test-server-static-imports]] |
||||
[[mockmvc-server-static-imports]] |
||||
= Static Imports |
||||
:page-section-summary-toc: 1 |
||||
|
||||
@ -1,4 +1,4 @@
@@ -1,4 +1,4 @@
|
||||
[[spring-mvc-test-vs-streaming-response]] |
||||
[[mockmvc-vs-streaming-response]] |
||||
= Streaming Responses |
||||
|
||||
You can use `WebTestClient` to test xref:testing/webtestclient.adoc#webtestclient-stream[streaming responses] |
||||
@ -1,8 +1,8 @@
@@ -1,8 +1,8 @@
|
||||
[[spring-mvc-test-server-htmlunit]] |
||||
[[mockmvc-server-htmlunit]] |
||||
= HtmlUnit Integration |
||||
:page-section-summary-toc: 1 |
||||
|
||||
Spring provides integration between xref:testing/spring-mvc-test-framework/server.adoc[MockMvc] and |
||||
Spring provides integration between xref:testing/mockmvc/overview.adoc[MockMvc] and |
||||
https://htmlunit.sourceforge.io/[HtmlUnit]. This simplifies performing end-to-end testing |
||||
when using HTML-based views. This integration lets you: |
||||
|
||||
@ -1,4 +1,4 @@
@@ -1,4 +1,4 @@
|
||||
[[spring-mvc-test-server-resources]] |
||||
[[mockmvc-server-resources]] |
||||
= Further Examples |
||||
:page-section-summary-toc: 1 |
||||
|
||||
@ -0,0 +1,29 @@
@@ -0,0 +1,29 @@
|
||||
[[mockmvc-server-setup-options]] |
||||
= Setup Options |
||||
|
||||
MockMvc can be setup in one of two ways. One is to point directly to the controllers you |
||||
want to test and programmatically configure Spring MVC infrastructure. The second is to |
||||
point to Spring configuration with Spring MVC and controller infrastructure in it. |
||||
|
||||
Which setup option should you use? |
||||
|
||||
The use of an `ApplicationContext` loads your actual Spring MVC configuration, resulting |
||||
The `WebApplicationContext`-based test loads your actual Spring MVC configuration, |
||||
resulting in a more complete integration test. Since the TestContext framework caches |
||||
the loaded Spring configuration, it helps keep tests running fast, even as you introduce |
||||
more tests in your test suite using the same configuration. Furthermore, you can |
||||
override services used by your controller using `@MockitoBean` to remain focused on |
||||
testing the web layer. |
||||
|
||||
The standalone test, on the other hand, is a little closer to a unit test. It tests one |
||||
controller at a time. You can manually inject the controller with mock dependencies, and |
||||
it does not involve loading Spring configuration. Such tests are more focused on style |
||||
and make it easier to see which controller is being tested, whether any specific Spring |
||||
MVC configuration is required to work, and so on. The standalone setup is also a very |
||||
convenient way to write ad-hoc tests to verify specific behavior or to debug an issue. |
||||
|
||||
As with most "`integration versus unit testing`" debates, there is no right or wrong |
||||
answer. However, using standalone tests does imply the need for additional integration |
||||
tests to verify your Spring MVC configuration. Alternatively, you can write all your |
||||
tests with a `WebApplicationContext`, so that they always test against your actual Spring |
||||
MVC configuration. |
||||
@ -1,4 +1,4 @@
@@ -1,4 +1,4 @@
|
||||
[[spring-mvc-test-vs-end-to-end-integration-tests]] |
||||
[[mockmvc-vs-end-to-end-integration-tests]] |
||||
= MockMvc vs End-to-End Tests |
||||
|
||||
MockMvc is built on Servlet API mock implementations from the |
||||
@ -1,15 +0,0 @@
@@ -1,15 +0,0 @@
|
||||
[[spring-mvc-test-framework]] |
||||
= MockMvc |
||||
:page-section-summary-toc: 1 |
||||
|
||||
The Spring MVC Test framework, also known as MockMvc, provides support for testing Spring |
||||
MVC applications. It performs full Spring MVC request handling but via mock request and |
||||
response objects instead of a running server. |
||||
|
||||
MockMvc can be used on its own to perform requests and verify responses. It can also be |
||||
used through the xref:testing/webtestclient.adoc[WebTestClient] where MockMvc is plugged in as the server to handle |
||||
requests with. The advantage of `WebTestClient` is the option to work with higher level |
||||
objects instead of raw data as well as the ability to switch to full, end-to-end HTTP |
||||
tests against a live server and use the same test API. |
||||
|
||||
|
||||
@ -1,181 +0,0 @@
@@ -1,181 +0,0 @@
|
||||
[[spring-mvc-test-server-setup-options]] |
||||
= Setup Choices |
||||
|
||||
MockMvc can be setup in one of two ways. One is to point directly to the controllers you |
||||
want to test and programmatically configure Spring MVC infrastructure. The second is to |
||||
point to Spring configuration with Spring MVC and controller infrastructure in it. |
||||
|
||||
To set up MockMvc for testing a specific controller, use the following: |
||||
|
||||
[tabs] |
||||
====== |
||||
Java:: |
||||
+ |
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
||||
---- |
||||
class MyWebTests { |
||||
|
||||
MockMvc mockMvc; |
||||
|
||||
@BeforeEach |
||||
void setup() { |
||||
this.mockMvc = MockMvcBuilders.standaloneSetup(new AccountController()).build(); |
||||
} |
||||
|
||||
// ... |
||||
|
||||
} |
||||
---- |
||||
|
||||
Kotlin:: |
||||
+ |
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
||||
---- |
||||
class MyWebTests { |
||||
|
||||
lateinit var mockMvc : MockMvc |
||||
|
||||
@BeforeEach |
||||
fun setup() { |
||||
mockMvc = MockMvcBuilders.standaloneSetup(AccountController()).build() |
||||
} |
||||
|
||||
// ... |
||||
|
||||
} |
||||
---- |
||||
====== |
||||
|
||||
Or you can also use this setup when testing through the |
||||
xref:testing/webtestclient.adoc#webtestclient-controller-config[WebTestClient] which delegates to the same builder |
||||
as shown above. |
||||
|
||||
To set up MockMvc through Spring configuration, use the following: |
||||
|
||||
[tabs] |
||||
====== |
||||
Java:: |
||||
+ |
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
||||
---- |
||||
@SpringJUnitWebConfig(locations = "my-servlet-context.xml") |
||||
class MyWebTests { |
||||
|
||||
MockMvc mockMvc; |
||||
|
||||
@BeforeEach |
||||
void setup(WebApplicationContext wac) { |
||||
this.mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); |
||||
} |
||||
|
||||
// ... |
||||
|
||||
} |
||||
---- |
||||
|
||||
Kotlin:: |
||||
+ |
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
||||
---- |
||||
@SpringJUnitWebConfig(locations = ["my-servlet-context.xml"]) |
||||
class MyWebTests { |
||||
|
||||
lateinit var mockMvc: MockMvc |
||||
|
||||
@BeforeEach |
||||
fun setup(wac: WebApplicationContext) { |
||||
mockMvc = MockMvcBuilders.webAppContextSetup(wac).build() |
||||
} |
||||
|
||||
// ... |
||||
|
||||
} |
||||
---- |
||||
====== |
||||
|
||||
Or you can also use this setup when testing through the |
||||
xref:testing/webtestclient.adoc#webtestclient-context-config[WebTestClient] which delegates to the same builder |
||||
as shown above. |
||||
|
||||
|
||||
|
||||
Which setup option should you use? |
||||
|
||||
The `webAppContextSetup` loads your actual Spring MVC configuration, resulting in a more |
||||
complete integration test. Since the TestContext framework caches the loaded Spring |
||||
configuration, it helps keep tests running fast, even as you introduce more tests in your |
||||
test suite. Furthermore, you can inject mock services into controllers through Spring |
||||
configuration to remain focused on testing the web layer. The following example declares |
||||
a mock service with Mockito: |
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes"] |
||||
---- |
||||
<bean id="accountService" class="org.mockito.Mockito" factory-method="mock"> |
||||
<constructor-arg type="java.lang.Class" value="org.example.AccountService"/> |
||||
<constructor-arg type="java.lang.String" value="accountService"/> |
||||
</bean> |
||||
---- |
||||
|
||||
You can then inject the mock service into the test to set up and verify your |
||||
expectations, as the following example shows: |
||||
|
||||
[tabs] |
||||
====== |
||||
Java:: |
||||
+ |
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
||||
---- |
||||
@SpringJUnitWebConfig(locations = "test-servlet-context.xml") |
||||
class AccountTests { |
||||
|
||||
@Autowired |
||||
AccountService accountService; |
||||
|
||||
MockMvc mockMvc; |
||||
|
||||
@BeforeEach |
||||
void setup(WebApplicationContext wac) { |
||||
this.mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); |
||||
} |
||||
|
||||
// ... |
||||
|
||||
} |
||||
---- |
||||
|
||||
Kotlin:: |
||||
+ |
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
||||
---- |
||||
@SpringJUnitWebConfig(locations = ["test-servlet-context.xml"]) |
||||
class AccountTests { |
||||
|
||||
@Autowired |
||||
lateinit var accountService: AccountService |
||||
|
||||
lateinit var mockMvc: MockMvc |
||||
|
||||
@BeforeEach |
||||
fun setup(wac: WebApplicationContext) { |
||||
mockMvc = MockMvcBuilders.webAppContextSetup(wac).build() |
||||
} |
||||
|
||||
// ... |
||||
|
||||
} |
||||
---- |
||||
====== |
||||
|
||||
The `standaloneSetup`, on the other hand, is a little closer to a unit test. It tests one |
||||
controller at a time. You can manually inject the controller with mock dependencies, and |
||||
it does not involve loading Spring configuration. Such tests are more focused on style |
||||
and make it easier to see which controller is being tested, whether any specific Spring |
||||
MVC configuration is required to work, and so on. The `standaloneSetup` is also a very |
||||
convenient way to write ad-hoc tests to verify specific behavior or to debug an issue. |
||||
|
||||
As with most "`integration versus unit testing`" debates, there is no right or wrong |
||||
answer. However, using the `standaloneSetup` does imply the need for additional |
||||
`webAppContextSetup` tests in order to verify your Spring MVC configuration. |
||||
Alternatively, you can write all your tests with `webAppContextSetup`, in order to always |
||||
test against your actual Spring MVC configuration. |
||||
|
||||
@ -0,0 +1,50 @@
@@ -0,0 +1,50 @@
|
||||
/* |
||||
* 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.docs.testing.mockmvc.assertj.mockmvctesterassertions; |
||||
|
||||
import org.springframework.http.HttpStatus; |
||||
import org.springframework.http.MediaType; |
||||
import org.springframework.test.web.servlet.assertj.MockMvcTester; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
|
||||
public class HotelControllerTests { |
||||
|
||||
private final MockMvcTester mockMvc = MockMvcTester.of(new HotelController()); |
||||
|
||||
|
||||
void getHotel() { |
||||
// tag::get[]
|
||||
assertThat(mockMvc.get().uri("/hotels/{id}", 42)) |
||||
.hasStatusOk() |
||||
.hasContentTypeCompatibleWith(MediaType.APPLICATION_JSON) |
||||
.bodyJson().isLenientlyEqualTo("sample/hotel-42.json"); |
||||
// end::get[]
|
||||
} |
||||
|
||||
|
||||
void getHotelInvalid() { |
||||
// tag::failure[]
|
||||
assertThat(mockMvc.get().uri("/hotels/{id}", -1)) |
||||
.hasFailed() |
||||
.hasStatus(HttpStatus.BAD_REQUEST) |
||||
.failure().hasMessageContaining("Identifier should be positive"); |
||||
// end::failure[]
|
||||
} |
||||
|
||||
static class HotelController {} |
||||
} |
||||
@ -0,0 +1,69 @@
@@ -0,0 +1,69 @@
|
||||
/* |
||||
* 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.docs.testing.mockmvc.assertj.mockmvctesterassertionsjson; |
||||
|
||||
import org.assertj.core.api.InstanceOfAssertFactories; |
||||
|
||||
import org.springframework.test.web.servlet.assertj.MockMvcTester; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
import static org.assertj.core.api.Assertions.entry; |
||||
|
||||
class FamilyControllerTests { |
||||
|
||||
private final MockMvcTester mockMvc = MockMvcTester.of(new FamilyController()); |
||||
|
||||
|
||||
void extractingPathAsMap() { |
||||
// tag::extract-asmap[]
|
||||
assertThat(mockMvc.get().uri("/family")).bodyJson() |
||||
.extractingPath("$.members[0]") |
||||
.asMap() |
||||
.contains(entry("name", "Homer")); |
||||
// end::extract-asmap[]
|
||||
} |
||||
|
||||
void extractingPathAndConvertWithType() { |
||||
// tag::extract-convert[]
|
||||
assertThat(mockMvc.get().uri("/family")).bodyJson() |
||||
.extractingPath("$.members[0]") |
||||
.convertTo(Member.class) |
||||
.satisfies(member -> assertThat(member.name).isEqualTo("Homer")); |
||||
// end::extract-convert[]
|
||||
} |
||||
|
||||
void extractingPathAndConvertWithAssertFactory() { |
||||
// tag::extract-convert-assert-factory[]
|
||||
assertThat(mockMvc.get().uri("/family")).bodyJson() |
||||
.extractingPath("$.members") |
||||
.convertTo(InstanceOfAssertFactories.list(Member.class)) |
||||
.hasSize(5) |
||||
.element(0).satisfies(member -> assertThat(member.name).isEqualTo("Homer")); |
||||
// end::extract-convert-assert-factory[]
|
||||
} |
||||
|
||||
void assertTheSimpsons() { |
||||
// tag::assert-file[]
|
||||
assertThat(mockMvc.get().uri("/family")).bodyJson() |
||||
.isStrictlyEqualTo("sample/simpsons.json"); |
||||
// end::assert-file[]
|
||||
} |
||||
|
||||
static class FamilyController {} |
||||
|
||||
record Member(String name) {} |
||||
} |
||||
@ -0,0 +1,47 @@
@@ -0,0 +1,47 @@
|
||||
/* |
||||
* 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.docs.testing.mockmvc.assertj.mockmvctesterintegration; |
||||
|
||||
import org.springframework.test.web.servlet.assertj.MockMvcTester; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; |
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; |
||||
|
||||
public class HotelControllerTests { |
||||
|
||||
private final MockMvcTester mockMvc = MockMvcTester.of(new HotelController()); |
||||
|
||||
|
||||
void perform() { |
||||
// tag::perform[]
|
||||
// Static import on MockMvcRequestBuilders.get
|
||||
assertThat(mockMvc.perform(get("/hotels/{id}", 42))) |
||||
.hasStatusOk(); |
||||
// end::perform[]
|
||||
} |
||||
|
||||
void performWithCustomMatcher() { |
||||
// tag::matches[]
|
||||
// Static import on MockMvcResultMatchers.status
|
||||
assertThat(mockMvc.get().uri("/hotels/{id}", 42)) |
||||
.matches(status().isOk()); |
||||
// end::matches[]
|
||||
} |
||||
|
||||
static class HotelController {} |
||||
} |
||||
@ -0,0 +1,68 @@
@@ -0,0 +1,68 @@
|
||||
/* |
||||
* 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.docs.testing.mockmvc.assertj.mockmvctesterrequests; |
||||
|
||||
import org.springframework.http.MediaType; |
||||
import org.springframework.test.web.servlet.assertj.MockMvcTester; |
||||
import org.springframework.test.web.servlet.assertj.MvcTestResult; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; |
||||
|
||||
/** |
||||
* @author Stephane Nicoll |
||||
*/ |
||||
public class HotelControllerTests { |
||||
|
||||
private final MockMvcTester mockMvc = MockMvcTester.of(new HotelController()); |
||||
|
||||
|
||||
void createHotel() { |
||||
// tag::post[]
|
||||
assertThat(mockMvc.post().uri("/hotels/{id}", 42).accept(MediaType.APPLICATION_JSON)) |
||||
. // ...
|
||||
// end::post[]
|
||||
hasStatusOk(); |
||||
} |
||||
|
||||
void createHotelMultipleAssertions() { |
||||
// tag::post-exchange[]
|
||||
MvcTestResult result = mockMvc.post().uri("/hotels/{id}", 42) |
||||
.accept(MediaType.APPLICATION_JSON).exchange(); |
||||
assertThat(result). // ...
|
||||
// end::post-exchange[]
|
||||
hasStatusOk(); |
||||
} |
||||
|
||||
void queryParameters() { |
||||
// tag::query-parameters[]
|
||||
assertThat(mockMvc.get().uri("/hotels?thing={thing}", "somewhere")) |
||||
. // ...
|
||||
// end::query-parameters[]
|
||||
hasStatusOk(); |
||||
} |
||||
|
||||
void parameters() { |
||||
// tag::parameters[]
|
||||
assertThat(mockMvc.get().uri("/hotels").param("thing", "somewhere")) |
||||
. // ...
|
||||
// end::parameters[]
|
||||
hasStatusOk(); |
||||
} |
||||
|
||||
static class HotelController {} |
||||
} |
||||
@ -0,0 +1,38 @@
@@ -0,0 +1,38 @@
|
||||
/* |
||||
* 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.docs.testing.mockmvc.assertj.mockmvctesterrequestsasync; |
||||
|
||||
import java.time.Duration; |
||||
|
||||
import org.springframework.test.web.servlet.assertj.MockMvcTester; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
|
||||
public class AsyncControllerTests { |
||||
|
||||
private final MockMvcTester mockMvc = MockMvcTester.of(new AsyncController()); |
||||
|
||||
void asyncExchangeWithCustomTimeToWait() { |
||||
// tag::duration[]
|
||||
assertThat(mockMvc.get().uri("/compute").exchange(Duration.ofSeconds(5))) |
||||
. // ...
|
||||
// end::duration[]
|
||||
hasStatusOk(); |
||||
} |
||||
|
||||
static class AsyncController {} |
||||
} |
||||
@ -0,0 +1,40 @@
@@ -0,0 +1,40 @@
|
||||
/* |
||||
* 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.docs.testing.mockmvc.assertj.mockmvctesterrequestsmultipart; |
||||
|
||||
import java.nio.charset.StandardCharsets; |
||||
|
||||
import org.springframework.test.web.servlet.assertj.MockMvcTester; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
|
||||
public class MultipartControllerTests { |
||||
|
||||
private final MockMvcTester mockMvc = MockMvcTester.of(new MultipartController()); |
||||
|
||||
void multiPart() { |
||||
// tag::snippet[]
|
||||
assertThat(mockMvc.post().uri("/upload").multipart() |
||||
.file("file1.txt", "Hello".getBytes(StandardCharsets.UTF_8)) |
||||
.file("file2.txt", "World".getBytes(StandardCharsets.UTF_8))) |
||||
. // ...
|
||||
// end::snippet[]
|
||||
hasStatusOk(); |
||||
} |
||||
|
||||
static class MultipartController {} |
||||
} |
||||
@ -0,0 +1,54 @@
@@ -0,0 +1,54 @@
|
||||
/* |
||||
* 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.docs.testing.mockmvc.assertj.mockmvctesterrequestspaths; |
||||
|
||||
import java.util.List; |
||||
|
||||
import org.springframework.http.MediaType; |
||||
import org.springframework.test.web.servlet.assertj.MockMvcTester; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; |
||||
|
||||
/** |
||||
* @author Stephane Nicoll |
||||
*/ |
||||
public class HotelControllerTests { |
||||
|
||||
private final MockMvcTester mockMvc = MockMvcTester.of(new HotelController()); |
||||
|
||||
void contextAndServletPaths() { |
||||
// tag::context-servlet-paths[]
|
||||
assertThat(mockMvc.get().uri("/app/main/hotels/{id}", 42) |
||||
.contextPath("/app").servletPath("/main")) |
||||
. // ...
|
||||
// end::context-servlet-paths[]
|
||||
hasStatusOk(); |
||||
} |
||||
|
||||
void configureMockMvcTesterWithDefaultSettings() { |
||||
// tag::default-customizations[]
|
||||
MockMvcTester mockMvc = MockMvcTester.of(List.of(new HotelController()), |
||||
builder -> builder.defaultRequest(get("/") |
||||
.contextPath("/app").servletPath("/main") |
||||
.accept(MediaType.APPLICATION_JSON)).build()); |
||||
// end::default-customizations[]
|
||||
} |
||||
|
||||
|
||||
static class HotelController {} |
||||
} |
||||
@ -0,0 +1,25 @@
@@ -0,0 +1,25 @@
|
||||
/* |
||||
* 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.docs.testing.mockmvc.assertj.mockmvctestersetup; |
||||
|
||||
import org.springframework.web.bind.annotation.RestController; |
||||
|
||||
@RestController |
||||
public class AccountController { |
||||
|
||||
|
||||
} |
||||
@ -0,0 +1,37 @@
@@ -0,0 +1,37 @@
|
||||
/* |
||||
* 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.docs.testing.mockmvc.assertj.mockmvctestersetup; |
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.test.context.junit.jupiter.web.SpringJUnitWebConfig; |
||||
import org.springframework.test.web.servlet.assertj.MockMvcTester; |
||||
import org.springframework.web.context.WebApplicationContext; |
||||
|
||||
// tag::snippet[]
|
||||
@SpringJUnitWebConfig(ApplicationWebConfiguration.class) |
||||
class AccountControllerIntegrationTests { |
||||
|
||||
private final MockMvcTester mockMvc; |
||||
|
||||
AccountControllerIntegrationTests(@Autowired WebApplicationContext wac) { |
||||
this.mockMvc = MockMvcTester.from(wac); |
||||
} |
||||
|
||||
// ...
|
||||
|
||||
} |
||||
// end::snippet[]
|
||||
@ -0,0 +1,29 @@
@@ -0,0 +1,29 @@
|
||||
/* |
||||
* 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.docs.testing.mockmvc.assertj.mockmvctestersetup; |
||||
|
||||
import org.springframework.test.web.servlet.assertj.MockMvcTester; |
||||
|
||||
// tag::snippet[]
|
||||
public class AccountControllerStandaloneTests { |
||||
|
||||
private final MockMvcTester mockMvc = MockMvcTester.of(new AccountController()); |
||||
|
||||
// ...
|
||||
|
||||
} |
||||
// end::snippet[]
|
||||
@ -0,0 +1,25 @@
@@ -0,0 +1,25 @@
|
||||
/* |
||||
* 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.docs.testing.mockmvc.assertj.mockmvctestersetup; |
||||
|
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc; |
||||
|
||||
@Configuration |
||||
@EnableWebMvc |
||||
public class ApplicationWebConfiguration { |
||||
} |
||||
@ -0,0 +1,42 @@
@@ -0,0 +1,42 @@
|
||||
/* |
||||
* 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.docs.testing.mockmvc.assertj.mockmvctestersetup.converter; |
||||
|
||||
import java.util.List; |
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.docs.testing.mockmvc.assertj.mockmvctestersetup.ApplicationWebConfiguration; |
||||
import org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter; |
||||
import org.springframework.test.context.junit.jupiter.web.SpringJUnitWebConfig; |
||||
import org.springframework.test.web.servlet.assertj.MockMvcTester; |
||||
import org.springframework.web.context.WebApplicationContext; |
||||
|
||||
// tag::snippet[]
|
||||
@SpringJUnitWebConfig(ApplicationWebConfiguration.class) |
||||
class AccountControllerIntegrationTests { |
||||
|
||||
private final MockMvcTester mockMvc; |
||||
|
||||
AccountControllerIntegrationTests(@Autowired WebApplicationContext wac) { |
||||
this.mockMvc = MockMvcTester.from(wac).withHttpMessageConverters( |
||||
List.of(wac.getBean(AbstractJackson2HttpMessageConverter.class))); |
||||
} |
||||
|
||||
// ...
|
||||
|
||||
} |
||||
// end::snippet[]
|
||||
@ -0,0 +1,48 @@
@@ -0,0 +1,48 @@
|
||||
/* |
||||
* 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.docs.testing.mockmvc.assertj.mockmvctesterassertions |
||||
|
||||
import org.assertj.core.api.Assertions.assertThat |
||||
import org.springframework.http.HttpStatus |
||||
import org.springframework.http.MediaType |
||||
import org.springframework.test.web.servlet.assertj.MockMvcTester |
||||
|
||||
class HotelControllerTests { |
||||
|
||||
private val mockMvc = MockMvcTester.of(HotelController()) |
||||
|
||||
fun getHotel() { |
||||
// tag::get[] |
||||
assertThat(mockMvc.get().uri("/hotels/{id}", 42)) |
||||
.hasStatusOk() |
||||
.hasContentTypeCompatibleWith(MediaType.APPLICATION_JSON) |
||||
.bodyJson().isLenientlyEqualTo("sample/hotel-42.json") |
||||
// end::get[] |
||||
} |
||||
|
||||
|
||||
fun getHotelInvalid() { |
||||
// tag::failure[] |
||||
assertThat(mockMvc.get().uri("/hotels/{id}", -1)) |
||||
.hasFailed() |
||||
.hasStatus(HttpStatus.BAD_REQUEST) |
||||
.failure().hasMessageContaining("Identifier should be positive") |
||||
// end::failure[] |
||||
} |
||||
|
||||
class HotelController |
||||
} |
||||
@ -0,0 +1,76 @@
@@ -0,0 +1,76 @@
|
||||
/* |
||||
* 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.docs.testing.mockmvc.assertj.mockmvctesterassertionsjson |
||||
|
||||
import org.assertj.core.api.Assertions.* |
||||
import org.assertj.core.api.InstanceOfAssertFactories |
||||
import org.assertj.core.api.ThrowingConsumer |
||||
import org.springframework.test.web.servlet.assertj.MockMvcTester |
||||
|
||||
/** |
||||
* |
||||
* @author Stephane Nicoll |
||||
*/ |
||||
class FamilyControllerTests { |
||||
|
||||
private val mockMvc = MockMvcTester.of(FamilyController()) |
||||
|
||||
|
||||
fun extractingPathAsMap() { |
||||
// tag::extract-asmap[] |
||||
assertThat(mockMvc.get().uri("/family")).bodyJson() |
||||
.extractingPath("$.members[0]") |
||||
.asMap() |
||||
.contains(entry("name", "Homer")) |
||||
// end::extract-asmap[] |
||||
} |
||||
|
||||
fun extractingPathAndConvertWithType() { |
||||
// tag::extract-convert[] |
||||
assertThat(mockMvc.get().uri("/family")).bodyJson() |
||||
.extractingPath("$.members[0]") |
||||
.convertTo(Member::class.java) |
||||
.satisfies(ThrowingConsumer { member: Member -> |
||||
assertThat(member.name).isEqualTo("Homer") |
||||
}) |
||||
// end::extract-convert[] |
||||
} |
||||
|
||||
fun extractingPathAndConvertWithAssertFactory() { |
||||
// tag::extract-convert-assert-factory[] |
||||
assertThat(mockMvc.get().uri("/family")).bodyJson() |
||||
.extractingPath("$.members") |
||||
.convertTo(InstanceOfAssertFactories.list(Member::class.java)) |
||||
.hasSize(5) |
||||
.element(0).satisfies(ThrowingConsumer { member: Member -> |
||||
assertThat(member.name).isEqualTo("Homer") |
||||
}) |
||||
// end::extract-convert-assert-factory[] |
||||
} |
||||
|
||||
fun assertTheSimpsons() { |
||||
// tag::assert-file[] |
||||
assertThat(mockMvc.get().uri("/family")).bodyJson() |
||||
.isStrictlyEqualTo("sample/simpsons.json") |
||||
// end::assert-file[] |
||||
} |
||||
|
||||
class FamilyController |
||||
|
||||
@JvmRecord |
||||
data class Member(val name: String) |
||||
} |
||||
@ -0,0 +1,53 @@
@@ -0,0 +1,53 @@
|
||||
/* |
||||
* 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.docs.testing.mockmvc.assertj.mockmvctesterintegration |
||||
|
||||
import org.assertj.core.api.Assertions |
||||
import org.assertj.core.api.Assertions.* |
||||
import org.springframework.test.web.servlet.assertj.MockMvcTester |
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders |
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.* |
||||
import org.springframework.test.web.servlet.result.MockMvcResultMatchers |
||||
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.* |
||||
|
||||
/** |
||||
* |
||||
* @author Stephane Nicoll |
||||
*/ |
||||
class HotelController { |
||||
|
||||
private val mockMvc = MockMvcTester.of(HotelController()) |
||||
|
||||
|
||||
fun perform() { |
||||
// tag::perform[] |
||||
// Static import on MockMvcRequestBuilders.get |
||||
assertThat(mockMvc.perform(get("/hotels/{id}",42))) |
||||
.hasStatusOk() |
||||
// end::perform[] |
||||
} |
||||
|
||||
fun performWithCustomMatcher() { |
||||
// tag::perform[] |
||||
// Static import on MockMvcResultMatchers.status |
||||
assertThat(mockMvc.get().uri("/hotels/{id}", 42)) |
||||
.matches(status().isOk()) |
||||
// end::perform[] |
||||
} |
||||
|
||||
class HotelController |
||||
} |
||||
@ -0,0 +1,62 @@
@@ -0,0 +1,62 @@
|
||||
/* |
||||
* 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.docs.testing.mockmvc.assertj.mockmvctesterrequests |
||||
|
||||
import org.assertj.core.api.Assertions.assertThat |
||||
import org.springframework.http.MediaType |
||||
import org.springframework.test.web.servlet.assertj.MockMvcTester |
||||
|
||||
class HotelControllerTests { |
||||
|
||||
private val mockMvc = MockMvcTester.of(HotelController()) |
||||
|
||||
fun createHotel() { |
||||
// tag::post[] |
||||
assertThat(mockMvc.post().uri("/hotels/{id}", 42).accept(MediaType.APPLICATION_JSON)) |
||||
. // ... |
||||
// end::post[] |
||||
hasStatusOk() |
||||
} |
||||
|
||||
fun createHotelMultipleAssertions() { |
||||
// tag::post-exchange[] |
||||
val result = mockMvc.post().uri("/hotels/{id}", 42) |
||||
.accept(MediaType.APPLICATION_JSON).exchange() |
||||
assertThat(result) |
||||
. // ... |
||||
// end::post-exchange[] |
||||
hasStatusOk() |
||||
} |
||||
|
||||
fun queryParameters() { |
||||
// tag::query-parameters[] |
||||
assertThat(mockMvc.get().uri("/hotels?thing={thing}", "somewhere")) |
||||
. // ... |
||||
//end::query-parameters[] |
||||
hasStatusOk() |
||||
} |
||||
|
||||
fun parameters() { |
||||
// tag::parameters[] |
||||
assertThat(mockMvc.get().uri("/hotels").param("thing", "somewhere")) |
||||
. // ... |
||||
// end::parameters[] |
||||
hasStatusOk() |
||||
} |
||||
|
||||
class HotelController |
||||
} |
||||
@ -0,0 +1,36 @@
@@ -0,0 +1,36 @@
|
||||
/* |
||||
* 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.docs.testing.mockmvc.assertj.mockmvctesterrequestsasync |
||||
|
||||
import org.assertj.core.api.Assertions.assertThat |
||||
import org.springframework.test.web.servlet.assertj.MockMvcTester |
||||
import java.time.Duration |
||||
|
||||
class AsyncControllerTests { |
||||
|
||||
private val mockMvc = MockMvcTester.of(AsyncController()) |
||||
|
||||
fun asyncExchangeWithCustomTimeToWait() { |
||||
// tag::duration[] |
||||
assertThat(mockMvc.get().uri("/compute").exchange(Duration.ofSeconds(5))) |
||||
. // ... |
||||
// end::duration[] |
||||
hasStatusOk() |
||||
} |
||||
|
||||
class AsyncController |
||||
} |
||||
@ -0,0 +1,42 @@
@@ -0,0 +1,42 @@
|
||||
/* |
||||
* 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.docs.testing.mockmvc.assertj.mockmvctesterrequestsmultipart |
||||
|
||||
import org.assertj.core.api.Assertions.assertThat |
||||
import org.springframework.test.web.servlet.assertj.MockMvcTester |
||||
import java.nio.charset.StandardCharsets |
||||
|
||||
/** |
||||
* |
||||
* @author Stephane Nicoll |
||||
*/ |
||||
class MultipartControllerTests { |
||||
|
||||
private val mockMvc = MockMvcTester.of(MultipartController()) |
||||
|
||||
fun multiPart() { |
||||
// tag::snippet[] |
||||
assertThat(mockMvc.post().uri("/upload").multipart() |
||||
.file("file1.txt", "Hello".toByteArray(StandardCharsets.UTF_8)) |
||||
.file("file2.txt", "World".toByteArray(StandardCharsets.UTF_8))) |
||||
. // ... |
||||
// end::snippet[] |
||||
hasStatusOk() |
||||
} |
||||
|
||||
class MultipartController |
||||
} |
||||
@ -0,0 +1,54 @@
@@ -0,0 +1,54 @@
|
||||
/* |
||||
* 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.docs.testing.mockmvc.assertj.mockmvctesterrequestspaths |
||||
|
||||
import org.assertj.core.api.Assertions.assertThat |
||||
import org.springframework.http.MediaType |
||||
import org.springframework.test.web.servlet.assertj.MockMvcTester |
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders |
||||
import org.springframework.test.web.servlet.setup.StandaloneMockMvcBuilder |
||||
|
||||
class HotelControllerTests { |
||||
|
||||
private val mockMvc = MockMvcTester.of(HotelController()) |
||||
|
||||
fun contextAndServletPaths() { |
||||
// tag::context-servlet-paths[] |
||||
assertThat(mockMvc.get().uri("/app/main/hotels/{id}", 42) |
||||
.contextPath("/app").servletPath("/main")) |
||||
. // ... |
||||
// end::context-servlet-paths[] |
||||
hasStatusOk() |
||||
} |
||||
|
||||
fun configureMockMvcTesterWithDefaultSettings() { |
||||
// tag::default-customizations[] |
||||
val mockMvc = |
||||
MockMvcTester.of(listOf(HotelController())) { builder: StandaloneMockMvcBuilder -> |
||||
builder.defaultRequest<StandaloneMockMvcBuilder>( |
||||
MockMvcRequestBuilders.get("/") |
||||
.contextPath("/app").servletPath("/main") |
||||
.accept(MediaType.APPLICATION_JSON) |
||||
).build() |
||||
} |
||||
// end::default-customizations[] |
||||
mockMvc.toString() // avoid warning |
||||
} |
||||
|
||||
|
||||
class HotelController |
||||
} |
||||
@ -0,0 +1,34 @@
@@ -0,0 +1,34 @@
|
||||
/* |
||||
* 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.docs.testing.mockmvc.assertj.mockmvctestersetup |
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired |
||||
import org.springframework.test.context.junit.jupiter.web.SpringJUnitWebConfig |
||||
import org.springframework.test.web.servlet.assertj.MockMvcTester |
||||
import org.springframework.web.context.WebApplicationContext |
||||
|
||||
// tag::snippet[] |
||||
@SpringJUnitWebConfig(ApplicationWebConfiguration::class) |
||||
class AccountControllerIntegrationTests(@Autowired wac: WebApplicationContext) { |
||||
|
||||
private val mockMvc = MockMvcTester.from(wac) |
||||
|
||||
// ... |
||||
|
||||
} |
||||
// end::snippet[] |
||||
|
||||
@ -0,0 +1,29 @@
@@ -0,0 +1,29 @@
|
||||
/* |
||||
* 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.docs.testing.mockmvc.assertj.mockmvctestersetup |
||||
|
||||
import org.springframework.test.web.servlet.assertj.MockMvcTester |
||||
|
||||
// tag::snippet[] |
||||
class AccountControllerStandaloneTests { |
||||
|
||||
val mockMvc = MockMvcTester.of(AccountController()) |
||||
|
||||
// ... |
||||
|
||||
} |
||||
// end::snippet[] |
||||
@ -0,0 +1,37 @@
@@ -0,0 +1,37 @@
|
||||
/* |
||||
* 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.docs.testing.mockmvc.assertj.mockmvctestersetup.converter |
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired |
||||
import org.springframework.docs.testing.mockmvc.assertj.mockmvctestersetup.ApplicationWebConfiguration |
||||
import org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter |
||||
import org.springframework.test.context.junit.jupiter.web.SpringJUnitWebConfig |
||||
import org.springframework.test.web.servlet.assertj.MockMvcTester |
||||
import org.springframework.web.context.WebApplicationContext |
||||
|
||||
// tag::snippet[] |
||||
@SpringJUnitWebConfig(ApplicationWebConfiguration::class) |
||||
class AccountControllerIntegrationTests(@Autowired wac: WebApplicationContext) { |
||||
|
||||
private val mockMvc = MockMvcTester.from(wac).withHttpMessageConverters( |
||||
listOf(wac.getBean(AbstractJackson2HttpMessageConverter::class.java))) |
||||
|
||||
// ... |
||||
|
||||
} |
||||
// end::snippet[] |
||||
|
||||
Loading…
Reference in new issue