From d43dba63a1caae9f167959c8be99d7c655c39a81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Nicoll?= Date: Fri, 21 Jun 2024 12:50:36 +0200 Subject: [PATCH] Document AssertJ support for MockMvc 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-32454 --- framework-docs/framework-docs.gradle | 1 + framework-docs/modules/ROOT/nav.adoc | 41 ++-- .../ROOT/pages/testing/integration.adoc | 2 +- .../modules/ROOT/pages/testing/mockmvc.adoc | 16 ++ .../ROOT/pages/testing/mockmvc/assertj.adoc | 16 ++ .../testing/mockmvc/assertj/assertions.adoc | 49 +++++ .../testing/mockmvc/assertj/integration.adoc | 23 +++ .../testing/mockmvc/assertj/requests.adoc | 83 ++++++++ .../pages/testing/mockmvc/assertj/setup.adoc | 30 +++ .../ROOT/pages/testing/mockmvc/hamcrest.adoc | 7 + .../hamcrest}/async-requests.adoc | 2 +- .../hamcrest/expectations.adoc} | 2 +- .../hamcrest/filters.adoc} | 2 +- .../hamcrest/requests.adoc} | 2 +- .../hamcrest/setup-steps.adoc} | 2 +- .../pages/testing/mockmvc/hamcrest/setup.adoc | 100 ++++++++++ .../hamcrest/static-imports.adoc} | 2 +- .../hamcrest}/vs-streaming-response.adoc | 2 +- .../htmlunit.adoc} | 4 +- .../htmlunit}/geb.adoc | 14 +- .../htmlunit}/mah.adoc | 16 +- .../htmlunit}/webdriver.adoc | 22 +-- .../htmlunit}/why.adoc | 16 +- .../server.adoc => mockmvc/overview.adoc} | 14 +- .../resources.adoc} | 2 +- .../pages/testing/mockmvc/setup-options.adoc | 29 +++ .../vs-end-to-end-integration-tests.adoc | 2 +- .../testing/spring-mvc-test-framework.adoc | 15 -- .../server-setup-options.adoc | 181 ------------------ .../modules/ROOT/pages/testing/unit.adoc | 6 +- .../ROOT/pages/testing/webtestclient.adoc | 4 +- .../modules/ROOT/pages/web/webmvc-test.adoc | 2 +- .../HotelControllerTests.java | 50 +++++ .../FamilyControllerTests.java | 69 +++++++ .../HotelControllerTests.java | 47 +++++ .../HotelControllerTests.java | 68 +++++++ .../AsyncControllerTests.java | 38 ++++ .../MultipartControllerTests.java | 40 ++++ .../HotelControllerTests.java | 54 ++++++ .../mockmvctestersetup/AccountController.java | 25 +++ .../AccountControllerIntegrationTests.java | 37 ++++ .../AccountControllerStandaloneTests.java | 29 +++ .../ApplicationWebConfiguration.java | 25 +++ .../AccountControllerIntegrationTests.java | 42 ++++ .../HotelControllerTests.kt | 48 +++++ .../FamilyControllerTests.kt | 76 ++++++++ .../HotelController.kt | 53 +++++ .../HotelControllerTests.kt | 62 ++++++ .../AsyncControllerTests.kt | 36 ++++ .../MultipartControllerTests.kt | 42 ++++ .../HotelControllerTests.kt | 54 ++++++ .../AccountControllerIntegrationTests.kt | 34 ++++ .../AccountControllerStandaloneTests.kt | 29 +++ .../AccountControllerIntegrationTests.kt | 37 ++++ 54 files changed, 1432 insertions(+), 272 deletions(-) create mode 100644 framework-docs/modules/ROOT/pages/testing/mockmvc.adoc create mode 100644 framework-docs/modules/ROOT/pages/testing/mockmvc/assertj.adoc create mode 100644 framework-docs/modules/ROOT/pages/testing/mockmvc/assertj/assertions.adoc create mode 100644 framework-docs/modules/ROOT/pages/testing/mockmvc/assertj/integration.adoc create mode 100644 framework-docs/modules/ROOT/pages/testing/mockmvc/assertj/requests.adoc create mode 100644 framework-docs/modules/ROOT/pages/testing/mockmvc/assertj/setup.adoc create mode 100644 framework-docs/modules/ROOT/pages/testing/mockmvc/hamcrest.adoc rename framework-docs/modules/ROOT/pages/testing/{spring-mvc-test-framework => mockmvc/hamcrest}/async-requests.adoc (98%) rename framework-docs/modules/ROOT/pages/testing/{spring-mvc-test-framework/server-defining-expectations.adoc => mockmvc/hamcrest/expectations.adoc} (99%) rename framework-docs/modules/ROOT/pages/testing/{spring-mvc-test-framework/server-filters.adoc => mockmvc/hamcrest/filters.adoc} (95%) rename framework-docs/modules/ROOT/pages/testing/{spring-mvc-test-framework/server-performing-requests.adoc => mockmvc/hamcrest/requests.adoc} (98%) rename framework-docs/modules/ROOT/pages/testing/{spring-mvc-test-framework/server-setup-steps.adoc => mockmvc/hamcrest/setup-steps.adoc} (97%) create mode 100644 framework-docs/modules/ROOT/pages/testing/mockmvc/hamcrest/setup.adoc rename framework-docs/modules/ROOT/pages/testing/{spring-mvc-test-framework/server-static-imports.adoc => mockmvc/hamcrest/static-imports.adoc} (93%) rename framework-docs/modules/ROOT/pages/testing/{spring-mvc-test-framework => mockmvc/hamcrest}/vs-streaming-response.adoc (95%) rename framework-docs/modules/ROOT/pages/testing/{spring-mvc-test-framework/server-htmlunit.adoc => mockmvc/htmlunit.adoc} (86%) rename framework-docs/modules/ROOT/pages/testing/{spring-mvc-test-framework/server-htmlunit => mockmvc/htmlunit}/geb.adoc (84%) rename framework-docs/modules/ROOT/pages/testing/{spring-mvc-test-framework/server-htmlunit => mockmvc/htmlunit}/mah.adoc (91%) rename framework-docs/modules/ROOT/pages/testing/{spring-mvc-test-framework/server-htmlunit => mockmvc/htmlunit}/webdriver.adoc (94%) rename framework-docs/modules/ROOT/pages/testing/{spring-mvc-test-framework/server-htmlunit => mockmvc/htmlunit}/why.adoc (92%) rename framework-docs/modules/ROOT/pages/testing/{spring-mvc-test-framework/server.adoc => mockmvc/overview.adoc} (62%) rename framework-docs/modules/ROOT/pages/testing/{spring-mvc-test-framework/server-resources.adoc => mockmvc/resources.adoc} (91%) create mode 100644 framework-docs/modules/ROOT/pages/testing/mockmvc/setup-options.adoc rename framework-docs/modules/ROOT/pages/testing/{spring-mvc-test-framework => mockmvc}/vs-end-to-end-integration-tests.adoc (98%) delete mode 100644 framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework.adoc delete mode 100644 framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-setup-options.adoc create mode 100644 framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterassertions/HotelControllerTests.java create mode 100644 framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterassertionsjson/FamilyControllerTests.java create mode 100644 framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterintegration/HotelControllerTests.java create mode 100644 framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterrequests/HotelControllerTests.java create mode 100644 framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterrequestsasync/AsyncControllerTests.java create mode 100644 framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterrequestsmultipart/MultipartControllerTests.java create mode 100644 framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterrequestspaths/HotelControllerTests.java create mode 100644 framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctestersetup/AccountController.java create mode 100644 framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctestersetup/AccountControllerIntegrationTests.java create mode 100644 framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctestersetup/AccountControllerStandaloneTests.java create mode 100644 framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctestersetup/ApplicationWebConfiguration.java create mode 100644 framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctestersetup/converter/AccountControllerIntegrationTests.java create mode 100644 framework-docs/src/main/kotlin/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterassertions/HotelControllerTests.kt create mode 100644 framework-docs/src/main/kotlin/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterassertionsjson/FamilyControllerTests.kt create mode 100644 framework-docs/src/main/kotlin/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterintegration/HotelController.kt create mode 100644 framework-docs/src/main/kotlin/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterrequests/HotelControllerTests.kt create mode 100644 framework-docs/src/main/kotlin/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterrequestsasync/AsyncControllerTests.kt create mode 100644 framework-docs/src/main/kotlin/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterrequestsmultipart/MultipartControllerTests.kt create mode 100644 framework-docs/src/main/kotlin/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterrequestspaths/HotelControllerTests.kt create mode 100644 framework-docs/src/main/kotlin/org/springframework/docs/testing/mockmvc/assertj/mockmvctestersetup/AccountControllerIntegrationTests.kt create mode 100644 framework-docs/src/main/kotlin/org/springframework/docs/testing/mockmvc/assertj/mockmvctestersetup/AccountControllerStandaloneTests.kt create mode 100644 framework-docs/src/main/kotlin/org/springframework/docs/testing/mockmvc/assertj/mockmvctestersetup/converter/AccountControllerIntegrationTests.kt diff --git a/framework-docs/framework-docs.gradle b/framework-docs/framework-docs.gradle index a150928d4e..60c852fc97 100644 --- a/framework-docs/framework-docs.gradle +++ b/framework-docs/framework-docs.gradle @@ -49,6 +49,7 @@ dependencies { api(project(":spring-webmvc")) api(project(":spring-context-support")) api(project(":spring-aspects")) + api(project(":spring-test")) api(project(":spring-websocket")) api("org.jetbrains.kotlin:kotlin-stdlib") diff --git a/framework-docs/modules/ROOT/nav.adoc b/framework-docs/modules/ROOT/nav.adoc index c6ca6b14a2..162a365a08 100644 --- a/framework-docs/modules/ROOT/nav.adoc +++ b/framework-docs/modules/ROOT/nav.adoc @@ -142,23 +142,30 @@ *** xref:testing/testcontext-framework/support-classes.adoc[] *** xref:testing/testcontext-framework/aot.adoc[] ** xref:testing/webtestclient.adoc[] -** xref:testing/spring-mvc-test-framework.adoc[] -*** xref:testing/spring-mvc-test-framework/server.adoc[] -*** xref:testing/spring-mvc-test-framework/server-static-imports.adoc[] -*** xref:testing/spring-mvc-test-framework/server-setup-options.adoc[] -*** xref:testing/spring-mvc-test-framework/server-setup-steps.adoc[] -*** xref:testing/spring-mvc-test-framework/server-performing-requests.adoc[] -*** xref:testing/spring-mvc-test-framework/server-defining-expectations.adoc[] -*** xref:testing/spring-mvc-test-framework/async-requests.adoc[] -*** xref:testing/spring-mvc-test-framework/vs-streaming-response.adoc[] -*** xref:testing/spring-mvc-test-framework/server-filters.adoc[] -*** xref:testing/spring-mvc-test-framework/vs-end-to-end-integration-tests.adoc[] -*** xref:testing/spring-mvc-test-framework/server-resources.adoc[] -*** xref:testing/spring-mvc-test-framework/server-htmlunit.adoc[] -**** xref:testing/spring-mvc-test-framework/server-htmlunit/why.adoc[] -**** xref:testing/spring-mvc-test-framework/server-htmlunit/mah.adoc[] -**** xref:testing/spring-mvc-test-framework/server-htmlunit/webdriver.adoc[] -**** xref:testing/spring-mvc-test-framework/server-htmlunit/geb.adoc[] +** xref:testing/mockmvc.adoc[] +*** xref:testing/mockmvc/overview.adoc[] +*** xref:testing/mockmvc/setup-options.adoc[] +*** xref:testing/mockmvc/hamcrest.adoc[] +**** xref:testing/mockmvc/hamcrest/static-imports.adoc[] +**** xref:testing/mockmvc/hamcrest/setup.adoc[] +**** xref:testing/mockmvc/hamcrest/setup-steps.adoc[] +**** xref:testing/mockmvc/hamcrest/requests.adoc[] +**** xref:testing/mockmvc/hamcrest/expectations.adoc[] +**** xref:testing/mockmvc/hamcrest/async-requests.adoc[] +**** xref:testing/mockmvc/hamcrest/vs-streaming-response.adoc[] +**** xref:testing/mockmvc/hamcrest/filters.adoc[] +*** xref:testing/mockmvc/assertj.adoc[] +**** xref:testing/mockmvc/assertj/setup.adoc[] +**** xref:testing/mockmvc/assertj/requests.adoc[] +**** xref:testing/mockmvc/assertj/assertions.adoc[] +**** xref:testing/mockmvc/assertj/integration.adoc[] +*** xref:testing/mockmvc/htmlunit.adoc[] +**** xref:testing/mockmvc/htmlunit/why.adoc[] +**** xref:testing/mockmvc/htmlunit/mah.adoc[] +**** xref:testing/mockmvc/htmlunit/webdriver.adoc[] +**** xref:testing/mockmvc/htmlunit/geb.adoc[] +*** xref:testing/mockmvc/vs-end-to-end-integration-tests.adoc[] +*** xref:testing/mockmvc/resources.adoc[] ** xref:testing/spring-mvc-test-client.adoc[] ** xref:testing/appendix.adoc[] *** xref:testing/annotations.adoc[] diff --git a/framework-docs/modules/ROOT/pages/testing/integration.adoc b/framework-docs/modules/ROOT/pages/testing/integration.adoc index a7a4b39729..79c2a83211 100644 --- a/framework-docs/modules/ROOT/pages/testing/integration.adoc +++ b/framework-docs/modules/ROOT/pages/testing/integration.adoc @@ -30,7 +30,7 @@ integration support, and the rest of this chapter then focuses on dedicated topi * xref:testing/support-jdbc.adoc[JDBC Testing Support] * xref:testing/testcontext-framework.adoc[Spring TestContext Framework] * xref:testing/webtestclient.adoc[WebTestClient] -* xref:testing/spring-mvc-test-framework.adoc[MockMvc] +* xref:testing/mockmvc.adoc[MockMvc] * xref:testing/spring-mvc-test-client.adoc[Testing Client Applications] * xref:testing/annotations.adoc[Annotations] diff --git a/framework-docs/modules/ROOT/pages/testing/mockmvc.adoc b/framework-docs/modules/ROOT/pages/testing/mockmvc.adoc new file mode 100644 index 0000000000..891a1f1c2c --- /dev/null +++ b/framework-docs/modules/ROOT/pages/testing/mockmvc.adoc @@ -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. + + diff --git a/framework-docs/modules/ROOT/pages/testing/mockmvc/assertj.adoc b/framework-docs/modules/ROOT/pages/testing/mockmvc/assertj.adoc new file mode 100644 index 0000000000..aa105c91b2 --- /dev/null +++ b/framework-docs/modules/ROOT/pages/testing/mockmvc/assertj.adoc @@ -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. \ No newline at end of file diff --git a/framework-docs/modules/ROOT/pages/testing/mockmvc/assertj/assertions.adoc b/framework-docs/modules/ROOT/pages/testing/mockmvc/assertj/assertions.adoc new file mode 100644 index 0000000000..bb3a9ca2bc --- /dev/null +++ b/framework-docs/modules/ROOT/pages/testing/mockmvc/assertj/assertions.adoc @@ -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`]. diff --git a/framework-docs/modules/ROOT/pages/testing/mockmvc/assertj/integration.adoc b/framework-docs/modules/ROOT/pages/testing/mockmvc/assertj/integration.adoc new file mode 100644 index 0000000000..25a77205d9 --- /dev/null +++ b/framework-docs/modules/ROOT/pages/testing/mockmvc/assertj/integration.adoc @@ -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`. + + diff --git a/framework-docs/modules/ROOT/pages/testing/mockmvc/assertj/requests.adoc b/framework-docs/modules/ROOT/pages/testing/mockmvc/assertj/requests.adoc new file mode 100644 index 0000000000..9889532fc1 --- /dev/null +++ b/framework-docs/modules/ROOT/pages/testing/mockmvc/assertj/requests.adoc @@ -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. + diff --git a/framework-docs/modules/ROOT/pages/testing/mockmvc/assertj/setup.adoc b/framework-docs/modules/ROOT/pages/testing/mockmvc/assertj/setup.adoc new file mode 100644 index 0000000000..5f0317c041 --- /dev/null +++ b/framework-docs/modules/ROOT/pages/testing/mockmvc/assertj/setup.adoc @@ -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. diff --git a/framework-docs/modules/ROOT/pages/testing/mockmvc/hamcrest.adoc b/framework-docs/modules/ROOT/pages/testing/mockmvc/hamcrest.adoc new file mode 100644 index 0000000000..46a1ecfa4e --- /dev/null +++ b/framework-docs/modules/ROOT/pages/testing/mockmvc/hamcrest.adoc @@ -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. \ No newline at end of file diff --git a/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/async-requests.adoc b/framework-docs/modules/ROOT/pages/testing/mockmvc/hamcrest/async-requests.adoc similarity index 98% rename from framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/async-requests.adoc rename to framework-docs/modules/ROOT/pages/testing/mockmvc/hamcrest/async-requests.adoc index 9dacf436fd..15e28e7775 100644 --- a/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/async-requests.adoc +++ b/framework-docs/modules/ROOT/pages/testing/mockmvc/hamcrest/async-requests.adoc @@ -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. diff --git a/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-defining-expectations.adoc b/framework-docs/modules/ROOT/pages/testing/mockmvc/hamcrest/expectations.adoc similarity index 99% rename from framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-defining-expectations.adoc rename to framework-docs/modules/ROOT/pages/testing/mockmvc/hamcrest/expectations.adoc index 27dbf6ed50..8820836abe 100644 --- a/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-defining-expectations.adoc +++ b/framework-docs/modules/ROOT/pages/testing/mockmvc/hamcrest/expectations.adoc @@ -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 diff --git a/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-filters.adoc b/framework-docs/modules/ROOT/pages/testing/mockmvc/hamcrest/filters.adoc similarity index 95% rename from framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-filters.adoc rename to framework-docs/modules/ROOT/pages/testing/mockmvc/hamcrest/filters.adoc index b292ec168a..e6be8e1e5f 100644 --- a/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-filters.adoc +++ b/framework-docs/modules/ROOT/pages/testing/mockmvc/hamcrest/filters.adoc @@ -1,4 +1,4 @@ -[[spring-mvc-test-server-filters]] +[[mockmvc-server-filters]] = Filter Registrations :page-section-summary-toc: 1 diff --git a/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-performing-requests.adoc b/framework-docs/modules/ROOT/pages/testing/mockmvc/hamcrest/requests.adoc similarity index 98% rename from framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-performing-requests.adoc rename to framework-docs/modules/ROOT/pages/testing/mockmvc/hamcrest/requests.adoc index 0d6bcab7ca..57a8404a17 100644 --- a/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-performing-requests.adoc +++ b/framework-docs/modules/ROOT/pages/testing/mockmvc/hamcrest/requests.adoc @@ -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. diff --git a/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-setup-steps.adoc b/framework-docs/modules/ROOT/pages/testing/mockmvc/hamcrest/setup-steps.adoc similarity index 97% rename from framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-setup-steps.adoc rename to framework-docs/modules/ROOT/pages/testing/mockmvc/hamcrest/setup-steps.adoc index e179a8364a..fd89ef4403 100644 --- a/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-setup-steps.adoc +++ b/framework-docs/modules/ROOT/pages/testing/mockmvc/hamcrest/setup-steps.adoc @@ -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 diff --git a/framework-docs/modules/ROOT/pages/testing/mockmvc/hamcrest/setup.adoc b/framework-docs/modules/ROOT/pages/testing/mockmvc/hamcrest/setup.adoc new file mode 100644 index 0000000000..483891eb1a --- /dev/null +++ b/framework-docs/modules/ROOT/pages/testing/mockmvc/hamcrest/setup.adoc @@ -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. diff --git a/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-static-imports.adoc b/framework-docs/modules/ROOT/pages/testing/mockmvc/hamcrest/static-imports.adoc similarity index 93% rename from framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-static-imports.adoc rename to framework-docs/modules/ROOT/pages/testing/mockmvc/hamcrest/static-imports.adoc index 21ccea1931..652eef58b3 100644 --- a/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-static-imports.adoc +++ b/framework-docs/modules/ROOT/pages/testing/mockmvc/hamcrest/static-imports.adoc @@ -1,4 +1,4 @@ -[[spring-mvc-test-server-static-imports]] +[[mockmvc-server-static-imports]] = Static Imports :page-section-summary-toc: 1 diff --git a/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/vs-streaming-response.adoc b/framework-docs/modules/ROOT/pages/testing/mockmvc/hamcrest/vs-streaming-response.adoc similarity index 95% rename from framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/vs-streaming-response.adoc rename to framework-docs/modules/ROOT/pages/testing/mockmvc/hamcrest/vs-streaming-response.adoc index 6a24b6ca7c..e7a5dba13f 100644 --- a/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/vs-streaming-response.adoc +++ b/framework-docs/modules/ROOT/pages/testing/mockmvc/hamcrest/vs-streaming-response.adoc @@ -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] diff --git a/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-htmlunit.adoc b/framework-docs/modules/ROOT/pages/testing/mockmvc/htmlunit.adoc similarity index 86% rename from framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-htmlunit.adoc rename to framework-docs/modules/ROOT/pages/testing/mockmvc/htmlunit.adoc index 03895dfa44..52cbacc3e7 100644 --- a/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-htmlunit.adoc +++ b/framework-docs/modules/ROOT/pages/testing/mockmvc/htmlunit.adoc @@ -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: diff --git a/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-htmlunit/geb.adoc b/framework-docs/modules/ROOT/pages/testing/mockmvc/htmlunit/geb.adoc similarity index 84% rename from framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-htmlunit/geb.adoc rename to framework-docs/modules/ROOT/pages/testing/mockmvc/htmlunit/geb.adoc index 8be8dd5292..ad4ece5513 100644 --- a/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-htmlunit/geb.adoc +++ b/framework-docs/modules/ROOT/pages/testing/mockmvc/htmlunit/geb.adoc @@ -1,18 +1,18 @@ -[[spring-mvc-test-server-htmlunit-geb]] +[[mockmvc-server-htmlunit-geb]] = MockMvc and Geb In the previous section, we saw how to use MockMvc with WebDriver. In this section, we use https://www.gebish.org/[Geb] to make our tests even Groovy-er. -[[spring-mvc-test-server-htmlunit-geb-why]] +[[mockmvc-server-htmlunit-geb-why]] == Why Geb and MockMvc? Geb is backed by WebDriver, so it offers many of the -xref:testing/spring-mvc-test-framework/server-htmlunit/webdriver.adoc#spring-mvc-test-server-htmlunit-webdriver-why[same benefits] that we get from +xref:testing/mockmvc/htmlunit/webdriver.adoc#spring-mvc-test-server-htmlunit-webdriver-why[same benefits] that we get from WebDriver. However, Geb makes things even easier by taking care of some of the boilerplate code for us. -[[spring-mvc-test-server-htmlunit-geb-setup]] +[[mockmvc-server-htmlunit-geb-setup]] == MockMvc and Geb Setup We can easily initialize a Geb `Browser` with a Selenium WebDriver that uses MockMvc, as @@ -28,14 +28,14 @@ def setup() { ---- NOTE: This is a simple example of using `MockMvcHtmlUnitDriverBuilder`. For more advanced -usage, see xref:testing/spring-mvc-test-framework/server-htmlunit/webdriver.adoc#spring-mvc-test-server-htmlunit-webdriver-advanced-builder[Advanced `MockMvcHtmlUnitDriverBuilder`]. +usage, see xref:testing/mockmvc/htmlunit/webdriver.adoc#spring-mvc-test-server-htmlunit-webdriver-advanced-builder[Advanced `MockMvcHtmlUnitDriverBuilder`]. This ensures that any URL referencing `localhost` as the server is directed to our `MockMvc` instance without the need for a real HTTP connection. Any other URL is requested by using a network connection as normal. This lets us easily test the use of CDNs. -[[spring-mvc-test-server-htmlunit-geb-usage]] +[[mockmvc-server-htmlunit-geb-usage]] == MockMvc and Geb Usage Now we can use Geb as we normally would but without the need to deploy our application to @@ -62,7 +62,7 @@ forwarded to the current page object. This removes a lot of the boilerplate code needed when using WebDriver directly. As with direct WebDriver usage, this improves on the design of our -xref:testing/spring-mvc-test-framework/server-htmlunit/mah.adoc#spring-mvc-test-server-htmlunit-mah-usage[HtmlUnit test] by using the Page Object +xref:testing/mockmvc/htmlunit/mah.adoc#spring-mvc-test-server-htmlunit-mah-usage[HtmlUnit test] by using the Page Object Pattern. As mentioned previously, we can use the Page Object Pattern with HtmlUnit and WebDriver, but it is even easier with Geb. Consider our new Groovy-based `CreateMessagePage` implementation: diff --git a/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-htmlunit/mah.adoc b/framework-docs/modules/ROOT/pages/testing/mockmvc/htmlunit/mah.adoc similarity index 91% rename from framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-htmlunit/mah.adoc rename to framework-docs/modules/ROOT/pages/testing/mockmvc/htmlunit/mah.adoc index 6578b5d8f9..e57612dbbf 100644 --- a/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-htmlunit/mah.adoc +++ b/framework-docs/modules/ROOT/pages/testing/mockmvc/htmlunit/mah.adoc @@ -1,10 +1,10 @@ -[[spring-mvc-test-server-htmlunit-mah]] +[[mockmvc-server-htmlunit-mah]] = MockMvc and HtmlUnit This section describes how to integrate MockMvc and HtmlUnit. Use this option if you want to use the raw HtmlUnit libraries. -[[spring-mvc-test-server-htmlunit-mah-setup]] +[[mockmvc-server-htmlunit-mah-setup]] == MockMvc and HtmlUnit Setup First, make sure that you have included a test dependency on @@ -45,14 +45,14 @@ Kotlin:: ====== NOTE: This is a simple example of using `MockMvcWebClientBuilder`. For advanced usage, -see xref:testing/spring-mvc-test-framework/server-htmlunit/mah.adoc#spring-mvc-test-server-htmlunit-mah-advanced-builder[Advanced `MockMvcWebClientBuilder`]. +see xref:testing/mockmvc/htmlunit/mah.adoc#spring-mvc-test-server-htmlunit-mah-advanced-builder[Advanced `MockMvcWebClientBuilder`]. This ensures that any URL that references `localhost` as the server is directed to our `MockMvc` instance without the need for a real HTTP connection. Any other URL is requested by using a network connection, as normal. This lets us easily test the use of CDNs. -[[spring-mvc-test-server-htmlunit-mah-usage]] +[[mockmvc-server-htmlunit-mah-usage]] == MockMvc and HtmlUnit Usage Now we can use HtmlUnit as we normally would but without the need to deploy our @@ -77,7 +77,7 @@ Kotlin:: ====== NOTE: The default context path is `""`. Alternatively, we can specify the context path, -as described in xref:testing/spring-mvc-test-framework/server-htmlunit/mah.adoc#spring-mvc-test-server-htmlunit-mah-advanced-builder[Advanced `MockMvcWebClientBuilder`]. +as described in xref:testing/mockmvc/htmlunit/mah.adoc#spring-mvc-test-server-htmlunit-mah-advanced-builder[Advanced `MockMvcWebClientBuilder`]. Once we have a reference to the `HtmlPage`, we can then fill out the form and submit it to create a message, as the following example shows: @@ -144,7 +144,7 @@ Kotlin:: ====== The preceding code improves on our -xref:testing/spring-mvc-test-framework/server-htmlunit/why.adoc#spring-mvc-test-server-htmlunit-mock-mvc-test[MockMvc test] in a number of ways. +xref:testing/mockmvc/htmlunit/why.adoc#spring-mvc-test-server-htmlunit-mock-mvc-test[MockMvc test] in a number of ways. First, we no longer have to explicitly verify our form and then create a request that looks like the form. Instead, we request the form, fill it out, and submit it, thereby significantly reducing the overhead. @@ -156,7 +156,7 @@ the behavior of JavaScript within our pages. See the https://htmlunit.sourceforge.io/gettingStarted.html[HtmlUnit documentation] for additional information about using HtmlUnit. -[[spring-mvc-test-server-htmlunit-mah-advanced-builder]] +[[mockmvc-server-htmlunit-mah-advanced-builder]] == Advanced `MockMvcWebClientBuilder` In the examples so far, we have used `MockMvcWebClientBuilder` in the simplest way @@ -275,5 +275,5 @@ This is more verbose, but, by building the `WebClient` with a `MockMvc` instance the full power of MockMvc at our fingertips. TIP: For additional information on creating a `MockMvc` instance, see -xref:testing/spring-mvc-test-framework/server-setup-options.adoc[Setup Choices]. +xref:testing/mockmvc/hamcrest/setup.adoc[Configuring MockMvc]. diff --git a/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-htmlunit/webdriver.adoc b/framework-docs/modules/ROOT/pages/testing/mockmvc/htmlunit/webdriver.adoc similarity index 94% rename from framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-htmlunit/webdriver.adoc rename to framework-docs/modules/ROOT/pages/testing/mockmvc/htmlunit/webdriver.adoc index 2c749b5e79..fedbdf9ef0 100644 --- a/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-htmlunit/webdriver.adoc +++ b/framework-docs/modules/ROOT/pages/testing/mockmvc/htmlunit/webdriver.adoc @@ -1,11 +1,11 @@ -[[spring-mvc-test-server-htmlunit-webdriver]] +[[mockmvc-server-htmlunit-webdriver]] = MockMvc and WebDriver In the previous sections, we have seen how to use MockMvc in conjunction with the raw HtmlUnit APIs. In this section, we use additional abstractions within the Selenium https://docs.seleniumhq.org/projects/webdriver/[WebDriver] to make things even easier. -[[spring-mvc-test-server-htmlunit-webdriver-why]] +[[mockmvc-server-htmlunit-webdriver-why]] == Why WebDriver and MockMvc? We can already use HtmlUnit and MockMvc, so why would we want to use WebDriver? The @@ -162,11 +162,11 @@ https://github.com/SeleniumHQ/selenium/wiki/PageObjects[Page Object Pattern]. Wh can certainly do this with HtmlUnit, WebDriver provides some tools that we explore in the following sections to make this pattern much easier to implement. -[[spring-mvc-test-server-htmlunit-webdriver-setup]] +[[mockmvc-server-htmlunit-webdriver-setup]] == MockMvc and WebDriver Setup -To use Selenium WebDriver with the Spring MVC Test framework, make sure that your project -includes a test dependency on `org.seleniumhq.selenium:selenium-htmlunit3-driver`. +To use Selenium WebDriver with `MockMvc`, make sure that your project includes a test +dependency on `org.seleniumhq.selenium:selenium-htmlunit3-driver`. We can easily create a Selenium WebDriver that integrates with MockMvc by using the `MockMvcHtmlUnitDriverBuilder` as the following example shows: @@ -203,14 +203,14 @@ Kotlin:: ====== NOTE: This is a simple example of using `MockMvcHtmlUnitDriverBuilder`. For more advanced -usage, see xref:testing/spring-mvc-test-framework/server-htmlunit/webdriver.adoc#spring-mvc-test-server-htmlunit-webdriver-advanced-builder[Advanced `MockMvcHtmlUnitDriverBuilder`]. +usage, see xref:testing/mockmvc/htmlunit/webdriver.adoc#spring-mvc-test-server-htmlunit-webdriver-advanced-builder[Advanced `MockMvcHtmlUnitDriverBuilder`]. The preceding example ensures that any URL that references `localhost` as the server is directed to our `MockMvc` instance without the need for a real HTTP connection. Any other URL is requested by using a network connection, as normal. This lets us easily test the use of CDNs. -[[spring-mvc-test-server-htmlunit-webdriver-usage]] +[[mockmvc-server-htmlunit-webdriver-usage]] == MockMvc and WebDriver Usage Now we can use WebDriver as we normally would but without the need to deploy our @@ -259,9 +259,9 @@ Kotlin:: ====== -- -This improves on the design of our xref:testing/spring-mvc-test-framework/server-htmlunit/mah.adoc#spring-mvc-test-server-htmlunit-mah-usage[HtmlUnit test] +This improves on the design of our xref:testing/mockmvc/htmlunit/mah.adoc#spring-mvc-test-server-htmlunit-mah-usage[HtmlUnit test] by leveraging the Page Object Pattern. As we mentioned in -xref:testing/spring-mvc-test-framework/server-htmlunit/webdriver.adoc#spring-mvc-test-server-htmlunit-webdriver-why[Why WebDriver and MockMvc?], we can use the Page Object Pattern +xref:testing/mockmvc/htmlunit/webdriver.adoc#spring-mvc-test-server-htmlunit-webdriver-why[Why WebDriver and MockMvc?], we can use the Page Object Pattern with HtmlUnit, but it is much easier with WebDriver. Consider the following `CreateMessagePage` implementation: @@ -451,7 +451,7 @@ Kotlin:: For additional information on using WebDriver, see the Selenium https://github.com/SeleniumHQ/selenium/wiki/Getting-Started[WebDriver documentation]. -[[spring-mvc-test-server-htmlunit-webdriver-advanced-builder]] +[[mockmvc-server-htmlunit-webdriver-advanced-builder]] == Advanced `MockMvcHtmlUnitDriverBuilder` In the examples so far, we have used `MockMvcHtmlUnitDriverBuilder` in the simplest way @@ -570,5 +570,5 @@ This is more verbose, but, by building the `WebDriver` with a `MockMvc` instance the full power of MockMvc at our fingertips. TIP: For additional information on creating a `MockMvc` instance, see -xref:testing/spring-mvc-test-framework/server-setup-options.adoc[Setup Choices]. +xref:testing/mockmvc/hamcrest/setup.adoc[Configuring MockMvc]. diff --git a/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-htmlunit/why.adoc b/framework-docs/modules/ROOT/pages/testing/mockmvc/htmlunit/why.adoc similarity index 92% rename from framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-htmlunit/why.adoc rename to framework-docs/modules/ROOT/pages/testing/mockmvc/htmlunit/why.adoc index e3f5935f33..3e1689f076 100644 --- a/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-htmlunit/why.adoc +++ b/framework-docs/modules/ROOT/pages/testing/mockmvc/htmlunit/why.adoc @@ -1,4 +1,4 @@ -[[spring-mvc-test-server-htmlunit-why]] +[[mockmvc-server-htmlunit-why]] = Why HtmlUnit Integration? The most obvious question that comes to mind is "`Why do I need this?`" The answer is @@ -94,7 +94,7 @@ follows: ====== Java:: + -[[spring-mvc-test-server-htmlunit-mock-mvc-test]] +[[mockmvc-server-htmlunit-mock-mvc-test]] [source,java,indent=0,subs="verbatim,quotes",role="primary"] ---- String summaryParamName = "summary"; @@ -151,7 +151,7 @@ the input to a user for creating a message. In addition, our form view can poten use additional resources that impact the behavior of the page, such as JavaScript validation. -[[spring-mvc-test-server-htmlunit-why-integration]] +[[mockmvc-server-htmlunit-why-integration]] == Integration Testing to the Rescue? To resolve the issues mentioned earlier, we could perform end-to-end integration testing, @@ -181,23 +181,23 @@ and without side effects. We can then implement a small number of true end-to-en integration tests that validate simple workflows to ensure that everything works together properly. -[[spring-mvc-test-server-htmlunit-why-mockmvc]] +[[mockmvc-server-htmlunit-why-mockmvc]] == Enter HtmlUnit Integration So how can we achieve a balance between testing the interactions of our pages and still retain good performance within our test suite? The answer is: "`By integrating MockMvc with HtmlUnit.`" -[[spring-mvc-test-server-htmlunit-options]] +[[mockmvc-server-htmlunit-options]] == HtmlUnit Integration Options You have a number of options when you want to integrate MockMvc with HtmlUnit: -* xref:testing/spring-mvc-test-framework/server-htmlunit/mah.adoc[MockMvc and HtmlUnit]: Use this option if you +* xref:testing/mockmvc/htmlunit/mah.adoc[MockMvc and HtmlUnit]: Use this option if you want to use the raw HtmlUnit libraries. -* xref:testing/spring-mvc-test-framework/server-htmlunit/webdriver.adoc[MockMvc and WebDriver]: Use this option to +* xref:testing/mockmvc/htmlunit/webdriver.adoc[MockMvc and WebDriver]: Use this option to ease development and reuse code between integration and end-to-end testing. -* xref:testing/spring-mvc-test-framework/server-htmlunit/geb.adoc[MockMvc and Geb]: Use this option if you want to +* xref:testing/mockmvc/htmlunit/geb.adoc[MockMvc and Geb]: Use this option if you want to use Groovy for testing, ease development, and reuse code between integration and end-to-end testing. diff --git a/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server.adoc b/framework-docs/modules/ROOT/pages/testing/mockmvc/overview.adoc similarity index 62% rename from framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server.adoc rename to framework-docs/modules/ROOT/pages/testing/mockmvc/overview.adoc index 2368a5a96c..f28fb27d94 100644 --- a/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server.adoc +++ b/framework-docs/modules/ROOT/pages/testing/mockmvc/overview.adoc @@ -1,4 +1,4 @@ -[[spring-mvc-test-server]] +[[mockmvc-overview]] = Overview :page-section-summary-toc: 1 @@ -8,17 +8,17 @@ mappings, data binding, message conversion, type conversion, validation, and nor do they involve any of the supporting `@InitBinder`, `@ModelAttribute`, or `@ExceptionHandler` methods. -The Spring MVC Test framework, also known as `MockMvc`, aims to provide more complete -testing for Spring MVC controllers without a running server. It does that by invoking -the `DispatcherServlet` and passing +`MockMvc` aims to provide more complete testing for Spring MVC controllers without a +running server. It does that by invoking the `DispatcherServlet` and passing xref:testing/unit.adoc#mock-objects-servlet["`mock`" implementations of the Servlet API] from the `spring-test` module which replicates the full Spring MVC request handling without a running server. MockMvc is a server side test framework that lets you verify most of the functionality of a Spring MVC application using lightweight and targeted tests. You can use it on -its own to perform requests and to verify responses, or you can also use it through -the xref:testing/webtestclient.adoc[WebTestClient] API with MockMvc plugged in as the server to handle requests -with. +its own to perform requests and to verify responses using Hamcrest, or through +`MockMvcTester` that provides a fluent API using AssertJ. Finally, you can also use it +through the xref:testing/webtestclient.adoc[WebTestClient] API with MockMvc plugged in +as the server to handle requests with. diff --git a/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-resources.adoc b/framework-docs/modules/ROOT/pages/testing/mockmvc/resources.adoc similarity index 91% rename from framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-resources.adoc rename to framework-docs/modules/ROOT/pages/testing/mockmvc/resources.adoc index cb9c8e97e8..a3fa509fcd 100644 --- a/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-resources.adoc +++ b/framework-docs/modules/ROOT/pages/testing/mockmvc/resources.adoc @@ -1,4 +1,4 @@ -[[spring-mvc-test-server-resources]] +[[mockmvc-server-resources]] = Further Examples :page-section-summary-toc: 1 diff --git a/framework-docs/modules/ROOT/pages/testing/mockmvc/setup-options.adoc b/framework-docs/modules/ROOT/pages/testing/mockmvc/setup-options.adoc new file mode 100644 index 0000000000..b2445f8887 --- /dev/null +++ b/framework-docs/modules/ROOT/pages/testing/mockmvc/setup-options.adoc @@ -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. diff --git a/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/vs-end-to-end-integration-tests.adoc b/framework-docs/modules/ROOT/pages/testing/mockmvc/vs-end-to-end-integration-tests.adoc similarity index 98% rename from framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/vs-end-to-end-integration-tests.adoc rename to framework-docs/modules/ROOT/pages/testing/mockmvc/vs-end-to-end-integration-tests.adoc index 9b3d38ccff..cbe8604974 100644 --- a/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/vs-end-to-end-integration-tests.adoc +++ b/framework-docs/modules/ROOT/pages/testing/mockmvc/vs-end-to-end-integration-tests.adoc @@ -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 diff --git a/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework.adoc b/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework.adoc deleted file mode 100644 index ec1900709d..0000000000 --- a/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework.adoc +++ /dev/null @@ -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. - - diff --git a/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-setup-options.adoc b/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-setup-options.adoc deleted file mode 100644 index 2abf6919d5..0000000000 --- a/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-setup-options.adoc +++ /dev/null @@ -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"] ----- - - - - ----- - -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. - diff --git a/framework-docs/modules/ROOT/pages/testing/unit.adoc b/framework-docs/modules/ROOT/pages/testing/unit.adoc index d2ce8648b0..6f6ce7a108 100644 --- a/framework-docs/modules/ROOT/pages/testing/unit.adoc +++ b/framework-docs/modules/ROOT/pages/testing/unit.adoc @@ -68,8 +68,8 @@ or alternative Servlet API mock objects (such as http://www.mockobjects.com[Mock TIP: Since Spring Framework 6.0, the mock objects in `org.springframework.mock.web` are based on the Servlet 6.0 API. -The Spring MVC Test framework builds on the mock Servlet API objects to provide an -integration testing framework for Spring MVC. See xref:testing/spring-mvc-test-framework.adoc[MockMvc]. +MockMvc builds on the mock Servlet API objects to provide an integration testing +framework for Spring MVC. See xref:testing/mockmvc.adoc[MockMvc]. [[mock-objects-web-reactive]] @@ -165,4 +165,4 @@ combined with `MockHttpServletRequest`, `MockHttpSession`, and so on from Spring xref:testing/unit.adoc#mock-objects-servlet[Servlet API mocks]. For thorough integration testing of your Spring MVC and REST `Controller` classes in conjunction with your `WebApplicationContext` configuration for Spring MVC, use the -xref:testing/spring-mvc-test-framework.adoc[Spring MVC Test Framework] instead. +xref:testing/mockmvc.adoc[MockMvc] instead. diff --git a/framework-docs/modules/ROOT/pages/testing/webtestclient.adoc b/framework-docs/modules/ROOT/pages/testing/webtestclient.adoc index f840531788..c1beaaad05 100644 --- a/framework-docs/modules/ROOT/pages/testing/webtestclient.adoc +++ b/framework-docs/modules/ROOT/pages/testing/webtestclient.adoc @@ -51,7 +51,7 @@ For Spring MVC, use the following which delegates to the {spring-framework-api}/test/web/servlet/setup/StandaloneMockMvcBuilder.html[StandaloneMockMvcBuilder] to load infrastructure equivalent to the xref:web/webmvc/mvc-config.adoc[WebMvc Java config], registers the given controller(s), and creates an instance of -xref:testing/spring-mvc-test-framework.adoc[MockMvc] to handle requests: +xref:testing/mockmvc.adoc[MockMvc] to handle requests: [tabs] ====== @@ -128,7 +128,7 @@ Kotlin:: For Spring MVC, use the following where the Spring `ApplicationContext` is passed to {spring-framework-api}/test/web/servlet/setup/MockMvcBuilders.html#webAppContextSetup-org.springframework.web.context.WebApplicationContext-[MockMvcBuilders.webAppContextSetup] -to create a xref:testing/spring-mvc-test-framework.adoc[MockMvc] instance to handle +to create a xref:testing/mockmvc.adoc[MockMvc] instance to handle requests: [tabs] diff --git a/framework-docs/modules/ROOT/pages/web/webmvc-test.adoc b/framework-docs/modules/ROOT/pages/web/webmvc-test.adoc index e5633bcea2..8456bdf015 100644 --- a/framework-docs/modules/ROOT/pages/web/webmvc-test.adoc +++ b/framework-docs/modules/ROOT/pages/web/webmvc-test.adoc @@ -16,7 +16,7 @@ See xref:testing/testcontext-framework.adoc[TestContext Framework] for more deta * Spring MVC Test: A framework, also known as `MockMvc`, for testing annotated controllers through the `DispatcherServlet` (that is, supporting annotations), complete with the Spring MVC infrastructure but without an HTTP server. -See xref:testing/spring-mvc-test-framework.adoc[Spring MVC Test] for more details. +See xref:testing/mockmvc.adoc[Spring MVC Test] for more details. * Client-side REST: `spring-test` provides a `MockRestServiceServer` that you can use as a mock server for testing client-side code that internally uses the `RestTemplate`. diff --git a/framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterassertions/HotelControllerTests.java b/framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterassertions/HotelControllerTests.java new file mode 100644 index 0000000000..647cb2099d --- /dev/null +++ b/framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterassertions/HotelControllerTests.java @@ -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 {} +} diff --git a/framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterassertionsjson/FamilyControllerTests.java b/framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterassertionsjson/FamilyControllerTests.java new file mode 100644 index 0000000000..96d41a2ea8 --- /dev/null +++ b/framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterassertionsjson/FamilyControllerTests.java @@ -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) {} +} diff --git a/framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterintegration/HotelControllerTests.java b/framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterintegration/HotelControllerTests.java new file mode 100644 index 0000000000..cc1e6b1c44 --- /dev/null +++ b/framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterintegration/HotelControllerTests.java @@ -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 {} +} diff --git a/framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterrequests/HotelControllerTests.java b/framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterrequests/HotelControllerTests.java new file mode 100644 index 0000000000..b72da0454c --- /dev/null +++ b/framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterrequests/HotelControllerTests.java @@ -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 {} +} diff --git a/framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterrequestsasync/AsyncControllerTests.java b/framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterrequestsasync/AsyncControllerTests.java new file mode 100644 index 0000000000..fa13d3abdf --- /dev/null +++ b/framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterrequestsasync/AsyncControllerTests.java @@ -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 {} +} diff --git a/framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterrequestsmultipart/MultipartControllerTests.java b/framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterrequestsmultipart/MultipartControllerTests.java new file mode 100644 index 0000000000..82371dd15c --- /dev/null +++ b/framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterrequestsmultipart/MultipartControllerTests.java @@ -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 {} +} diff --git a/framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterrequestspaths/HotelControllerTests.java b/framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterrequestspaths/HotelControllerTests.java new file mode 100644 index 0000000000..da39047300 --- /dev/null +++ b/framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterrequestspaths/HotelControllerTests.java @@ -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 {} +} diff --git a/framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctestersetup/AccountController.java b/framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctestersetup/AccountController.java new file mode 100644 index 0000000000..4a71ac3e43 --- /dev/null +++ b/framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctestersetup/AccountController.java @@ -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 { + + +} diff --git a/framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctestersetup/AccountControllerIntegrationTests.java b/framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctestersetup/AccountControllerIntegrationTests.java new file mode 100644 index 0000000000..0ec02321f2 --- /dev/null +++ b/framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctestersetup/AccountControllerIntegrationTests.java @@ -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[] diff --git a/framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctestersetup/AccountControllerStandaloneTests.java b/framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctestersetup/AccountControllerStandaloneTests.java new file mode 100644 index 0000000000..d14766d886 --- /dev/null +++ b/framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctestersetup/AccountControllerStandaloneTests.java @@ -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[] diff --git a/framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctestersetup/ApplicationWebConfiguration.java b/framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctestersetup/ApplicationWebConfiguration.java new file mode 100644 index 0000000000..7d9b7edebf --- /dev/null +++ b/framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctestersetup/ApplicationWebConfiguration.java @@ -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 { +} diff --git a/framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctestersetup/converter/AccountControllerIntegrationTests.java b/framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctestersetup/converter/AccountControllerIntegrationTests.java new file mode 100644 index 0000000000..63326e903a --- /dev/null +++ b/framework-docs/src/main/java/org/springframework/docs/testing/mockmvc/assertj/mockmvctestersetup/converter/AccountControllerIntegrationTests.java @@ -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[] diff --git a/framework-docs/src/main/kotlin/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterassertions/HotelControllerTests.kt b/framework-docs/src/main/kotlin/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterassertions/HotelControllerTests.kt new file mode 100644 index 0000000000..851eb323cc --- /dev/null +++ b/framework-docs/src/main/kotlin/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterassertions/HotelControllerTests.kt @@ -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 +} \ No newline at end of file diff --git a/framework-docs/src/main/kotlin/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterassertionsjson/FamilyControllerTests.kt b/framework-docs/src/main/kotlin/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterassertionsjson/FamilyControllerTests.kt new file mode 100644 index 0000000000..71faa576fc --- /dev/null +++ b/framework-docs/src/main/kotlin/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterassertionsjson/FamilyControllerTests.kt @@ -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) +} \ No newline at end of file diff --git a/framework-docs/src/main/kotlin/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterintegration/HotelController.kt b/framework-docs/src/main/kotlin/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterintegration/HotelController.kt new file mode 100644 index 0000000000..923c3557a5 --- /dev/null +++ b/framework-docs/src/main/kotlin/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterintegration/HotelController.kt @@ -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 +} \ No newline at end of file diff --git a/framework-docs/src/main/kotlin/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterrequests/HotelControllerTests.kt b/framework-docs/src/main/kotlin/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterrequests/HotelControllerTests.kt new file mode 100644 index 0000000000..3b0167dc82 --- /dev/null +++ b/framework-docs/src/main/kotlin/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterrequests/HotelControllerTests.kt @@ -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 +} \ No newline at end of file diff --git a/framework-docs/src/main/kotlin/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterrequestsasync/AsyncControllerTests.kt b/framework-docs/src/main/kotlin/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterrequestsasync/AsyncControllerTests.kt new file mode 100644 index 0000000000..5dc065b4dd --- /dev/null +++ b/framework-docs/src/main/kotlin/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterrequestsasync/AsyncControllerTests.kt @@ -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 +} \ No newline at end of file diff --git a/framework-docs/src/main/kotlin/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterrequestsmultipart/MultipartControllerTests.kt b/framework-docs/src/main/kotlin/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterrequestsmultipart/MultipartControllerTests.kt new file mode 100644 index 0000000000..07762bd7c6 --- /dev/null +++ b/framework-docs/src/main/kotlin/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterrequestsmultipart/MultipartControllerTests.kt @@ -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 +} \ No newline at end of file diff --git a/framework-docs/src/main/kotlin/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterrequestspaths/HotelControllerTests.kt b/framework-docs/src/main/kotlin/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterrequestspaths/HotelControllerTests.kt new file mode 100644 index 0000000000..2be16eab11 --- /dev/null +++ b/framework-docs/src/main/kotlin/org/springframework/docs/testing/mockmvc/assertj/mockmvctesterrequestspaths/HotelControllerTests.kt @@ -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( + MockMvcRequestBuilders.get("/") + .contextPath("/app").servletPath("/main") + .accept(MediaType.APPLICATION_JSON) + ).build() + } + // end::default-customizations[] + mockMvc.toString() // avoid warning + } + + + class HotelController +} \ No newline at end of file diff --git a/framework-docs/src/main/kotlin/org/springframework/docs/testing/mockmvc/assertj/mockmvctestersetup/AccountControllerIntegrationTests.kt b/framework-docs/src/main/kotlin/org/springframework/docs/testing/mockmvc/assertj/mockmvctestersetup/AccountControllerIntegrationTests.kt new file mode 100644 index 0000000000..5f86ee6c8e --- /dev/null +++ b/framework-docs/src/main/kotlin/org/springframework/docs/testing/mockmvc/assertj/mockmvctestersetup/AccountControllerIntegrationTests.kt @@ -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[] + diff --git a/framework-docs/src/main/kotlin/org/springframework/docs/testing/mockmvc/assertj/mockmvctestersetup/AccountControllerStandaloneTests.kt b/framework-docs/src/main/kotlin/org/springframework/docs/testing/mockmvc/assertj/mockmvctestersetup/AccountControllerStandaloneTests.kt new file mode 100644 index 0000000000..2d10ec032a --- /dev/null +++ b/framework-docs/src/main/kotlin/org/springframework/docs/testing/mockmvc/assertj/mockmvctestersetup/AccountControllerStandaloneTests.kt @@ -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[] \ No newline at end of file diff --git a/framework-docs/src/main/kotlin/org/springframework/docs/testing/mockmvc/assertj/mockmvctestersetup/converter/AccountControllerIntegrationTests.kt b/framework-docs/src/main/kotlin/org/springframework/docs/testing/mockmvc/assertj/mockmvctestersetup/converter/AccountControllerIntegrationTests.kt new file mode 100644 index 0000000000..523d728941 --- /dev/null +++ b/framework-docs/src/main/kotlin/org/springframework/docs/testing/mockmvc/assertj/mockmvctestersetup/converter/AccountControllerIntegrationTests.kt @@ -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[] +