Migrate to Asciidoctor Tabs
This commit is contained in:
@@ -16,8 +16,11 @@ first, then manually performing the async dispatch, and finally verifying the re
|
||||
Below is an example test for controller methods that return `DeferredResult`, `Callable`,
|
||||
or reactive type such as Reactor `Mono`:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
// static import of MockMvcRequestBuilders.* and MockMvcResultMatchers.*
|
||||
|
||||
@@ -34,6 +37,7 @@ or reactive type such as Reactor `Mono`:
|
||||
.andExpect(content().string("body"));
|
||||
}
|
||||
----
|
||||
======
|
||||
<1> Check response status is still unchanged
|
||||
<2> Async processing must have started
|
||||
<3> Wait and assert the async result
|
||||
|
||||
@@ -5,16 +5,20 @@ You can define expectations by appending one or more `andExpect(..)` calls after
|
||||
performing a request, as the following example shows. As soon as one expectation fails,
|
||||
no other expectations will be asserted.
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
// static import of MockMvcRequestBuilders.* and MockMvcResultMatchers.*
|
||||
|
||||
mockMvc.perform(get("/accounts/1")).andExpect(status().isOk());
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
import org.springframework.test.web.servlet.get
|
||||
|
||||
@@ -22,14 +26,18 @@ no other expectations will be asserted.
|
||||
status { isOk() }
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
You can define multiple expectations by appending `andExpectAll(..)` after performing a
|
||||
request, as the following example shows. In contrast to `andExpect(..)`,
|
||||
`andExpectAll(..)` guarantees that all supplied expectations will be asserted and that
|
||||
all failures will be tracked and reported.
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
// static import of MockMvcRequestBuilders.* and MockMvcResultMatchers.*
|
||||
|
||||
@@ -38,8 +46,9 @@ all failures will be tracked and reported.
|
||||
content().contentType("application/json;charset=UTF-8"));
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
import org.springframework.test.web.servlet.get
|
||||
|
||||
@@ -48,6 +57,7 @@ all failures will be tracked and reported.
|
||||
content { contentType(APPLICATION_JSON) }
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
`MockMvcResultMatchers.*` provides a number of expectations, some of which are further
|
||||
nested with more detailed expectations.
|
||||
@@ -64,16 +74,20 @@ inspect Servlet specific aspects, such as request and session attributes.
|
||||
|
||||
The following test asserts that binding or validation failed:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
mockMvc.perform(post("/persons"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(model().attributeHasErrors("person"));
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
import org.springframework.test.web.servlet.post
|
||||
|
||||
@@ -84,13 +98,17 @@ The following test asserts that binding or validation failed:
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
Many times, when writing tests, it is useful to dump the results of the performed
|
||||
request. You can do so as follows, where `print()` is a static import from
|
||||
`MockMvcResultHandlers`:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
mockMvc.perform(post("/persons"))
|
||||
.andDo(print())
|
||||
@@ -98,8 +116,9 @@ request. You can do so as follows, where `print()` is a static import from
|
||||
.andExpect(model().attributeHasErrors("person"));
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
import org.springframework.test.web.servlet.post
|
||||
|
||||
@@ -112,6 +131,7 @@ request. You can do so as follows, where `print()` is a static import from
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
As long as request processing does not cause an unhandled exception, the `print()` method
|
||||
prints all the available result data to `System.out`. There is also a `log()` method and
|
||||
@@ -126,36 +146,47 @@ In some cases, you may want to get direct access to the result and verify someth
|
||||
cannot be verified otherwise. This can be achieved by appending `.andReturn()` after all
|
||||
other expectations, as the following example shows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
MvcResult mvcResult = mockMvc.perform(post("/persons")).andExpect(status().isOk()).andReturn();
|
||||
// ...
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
var mvcResult = mockMvc.post("/persons").andExpect { status { isOk() } }.andReturn()
|
||||
// ...
|
||||
----
|
||||
======
|
||||
|
||||
If all tests repeat the same expectations, you can set up common expectations once when
|
||||
building the `MockMvc` instance, as the following example shows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
standaloneSetup(new SimpleController())
|
||||
.alwaysExpect(status().isOk())
|
||||
.alwaysExpect(content().contentType("application/json;charset=UTF-8"))
|
||||
.build()
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
// Not possible in Kotlin until https://youtrack.jetbrains.com/issue/KT-22208 is fixed
|
||||
----
|
||||
======
|
||||
|
||||
Note that common expectations are always applied and cannot be overridden without
|
||||
creating a separate `MockMvc` instance.
|
||||
@@ -164,15 +195,19 @@ When a JSON response content contains hypermedia links created with
|
||||
https://github.com/spring-projects/spring-hateoas[Spring HATEOAS], you can verify the
|
||||
resulting links by using JsonPath expressions, as the following example shows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
mockMvc.perform(get("/people").accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(jsonPath("$.links[?(@.rel == 'self')].href").value("http://localhost:8080/people"));
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
mockMvc.get("/people") {
|
||||
accept(MediaType.APPLICATION_JSON)
|
||||
@@ -182,21 +217,26 @@ resulting links by using JsonPath expressions, as the following example shows:
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
When XML response content contains hypermedia links created with
|
||||
https://github.com/spring-projects/spring-hateoas[Spring HATEOAS], you can verify the
|
||||
resulting links by using XPath expressions:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
Map<String, String> ns = Collections.singletonMap("ns", "http://www.w3.org/2005/Atom");
|
||||
mockMvc.perform(get("/handle").accept(MediaType.APPLICATION_XML))
|
||||
.andExpect(xpath("/person/ns:link[@rel='self']/@href", ns).string("http://localhost:8080/people"));
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
val ns = mapOf("ns" to "http://www.w3.org/2005/Atom")
|
||||
mockMvc.get("/handle") {
|
||||
@@ -207,4 +247,5 @@ resulting links by using XPath expressions:
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
|
||||
@@ -5,16 +5,22 @@
|
||||
When setting up a `MockMvc` instance, you can register one or more Servlet `Filter`
|
||||
instances, as the following example shows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
mockMvc = standaloneSetup(new PersonController()).addFilters(new CharacterEncodingFilter()).build();
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
// Not possible in Kotlin until https://youtrack.jetbrains.com/issue/KT-22208 is fixed
|
||||
----
|
||||
======
|
||||
|
||||
Registered filters are invoked through the `MockFilterChain` from `spring-test`, and the
|
||||
last filter delegates to the `DispatcherServlet`.
|
||||
|
||||
@@ -14,8 +14,11 @@ First, make sure that you have included a test dependency on
|
||||
We can easily create an HtmlUnit `WebClient` that integrates with MockMvc by using the
|
||||
`MockMvcWebClientBuilder`, as follows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
WebClient webClient;
|
||||
|
||||
@@ -27,8 +30,9 @@ We can easily create an HtmlUnit `WebClient` that integrates with MockMvc by usi
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
lateinit var webClient: WebClient
|
||||
|
||||
@@ -39,6 +43,7 @@ We can easily create an HtmlUnit `WebClient` that integrates with MockMvc by usi
|
||||
.build()
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
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`].
|
||||
@@ -55,17 +60,22 @@ Now we can use HtmlUnit as we normally would but without the need to deploy our
|
||||
application to a Servlet container. For example, we can request the view to create a
|
||||
message with the following:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
HtmlPage createMsgFormPage = webClient.getPage("http://localhost/messages/form");
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
val createMsgFormPage = webClient.getPage("http://localhost/messages/form")
|
||||
----
|
||||
======
|
||||
|
||||
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`].
|
||||
@@ -73,8 +83,11 @@ as described in xref:testing/spring-mvc-test-framework/server-htmlunit/mah.adoc#
|
||||
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:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
HtmlForm form = createMsgFormPage.getHtmlElementById("messageForm");
|
||||
HtmlTextInput summaryInput = createMsgFormPage.getHtmlElementById("summary");
|
||||
@@ -84,8 +97,10 @@ to create a message, as the following example shows:
|
||||
HtmlSubmitInput submit = form.getOneHtmlElementByAttribute("input", "type", "submit");
|
||||
HtmlPage newMessagePage = submit.click();
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
val form = createMsgFormPage.getHtmlElementById("messageForm")
|
||||
val summaryInput = createMsgFormPage.getHtmlElementById("summary")
|
||||
@@ -95,12 +110,16 @@ to create a message, as the following example shows:
|
||||
val submit = form.getOneHtmlElementByAttribute("input", "type", "submit")
|
||||
val newMessagePage = submit.click()
|
||||
----
|
||||
======
|
||||
|
||||
Finally, we can verify that a new message was created successfully. The following
|
||||
assertions use the https://assertj.github.io/doc/[AssertJ] library:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
assertThat(newMessagePage.getUrl().toString()).endsWith("/messages/123");
|
||||
String id = newMessagePage.getHtmlElementById("id").getTextContent();
|
||||
@@ -110,8 +129,10 @@ assertions use the https://assertj.github.io/doc/[AssertJ] library:
|
||||
String text = newMessagePage.getHtmlElementById("text").getTextContent();
|
||||
assertThat(text).isEqualTo("In case you didn't know, Spring Rocks!");
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
assertThat(newMessagePage.getUrl().toString()).endsWith("/messages/123")
|
||||
val id = newMessagePage.getHtmlElementById("id").getTextContent()
|
||||
@@ -121,6 +142,7 @@ assertions use the https://assertj.github.io/doc/[AssertJ] library:
|
||||
val text = newMessagePage.getHtmlElementById("text").getTextContent()
|
||||
assertThat(text).isEqualTo("In case you didn't know, Spring Rocks!")
|
||||
----
|
||||
======
|
||||
|
||||
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.
|
||||
@@ -142,8 +164,11 @@ In the examples so far, we have used `MockMvcWebClientBuilder` in the simplest w
|
||||
possible, by building a `WebClient` based on the `WebApplicationContext` loaded for us by
|
||||
the Spring TestContext Framework. This approach is repeated in the following example:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
WebClient webClient;
|
||||
|
||||
@@ -155,8 +180,9 @@ the Spring TestContext Framework. This approach is repeated in the following exa
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
lateinit var webClient: WebClient
|
||||
|
||||
@@ -167,11 +193,15 @@ the Spring TestContext Framework. This approach is repeated in the following exa
|
||||
.build()
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
We can also specify additional configuration options, as the following example shows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
WebClient webClient;
|
||||
|
||||
@@ -188,8 +218,10 @@ We can also specify additional configuration options, as the following example s
|
||||
.build();
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
lateinit var webClient: WebClient
|
||||
|
||||
@@ -206,12 +238,16 @@ We can also specify additional configuration options, as the following example s
|
||||
.build()
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
As an alternative, we can perform the exact same setup by configuring the `MockMvc`
|
||||
instance separately and supplying it to the `MockMvcWebClientBuilder`, as follows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
MockMvc mockMvc = MockMvcBuilders
|
||||
.webAppContextSetup(context)
|
||||
@@ -228,11 +264,13 @@ instance separately and supplying it to the `MockMvcWebClientBuilder`, as follow
|
||||
.build();
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
// Not possible in Kotlin until https://youtrack.jetbrains.com/issue/KT-22208 is fixed
|
||||
----
|
||||
======
|
||||
|
||||
This is more verbose, but, by building the `WebClient` with a `MockMvc` instance, we have
|
||||
the full power of MockMvc at our fingertips.
|
||||
|
||||
@@ -26,25 +26,34 @@ afterwards.
|
||||
If one of the fields were named "`summary`", we might have something that resembles the
|
||||
following repeated in multiple places within our tests:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
HtmlTextInput summaryInput = currentPage.getHtmlElementById("summary");
|
||||
summaryInput.setValueAttribute(summary);
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
val summaryInput = currentPage.getHtmlElementById("summary")
|
||||
summaryInput.setValueAttribute(summary)
|
||||
----
|
||||
======
|
||||
|
||||
So what happens if we change the `id` to `smmry`? Doing so would force us to update all
|
||||
of our tests to incorporate this change. This violates the DRY principle, so we should
|
||||
ideally extract this code into its own method, as follows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
public HtmlPage createMessage(HtmlPage currentPage, String summary, String text) {
|
||||
setSummary(currentPage, summary);
|
||||
@@ -57,8 +66,9 @@ ideally extract this code into its own method, as follows:
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
fun createMessage(currentPage: HtmlPage, summary:String, text:String) :HtmlPage{
|
||||
setSummary(currentPage, summary);
|
||||
@@ -70,14 +80,18 @@ ideally extract this code into its own method, as follows:
|
||||
summaryInput.setValueAttribute(summary)
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
Doing so ensures that we do not have to update all of our tests if we change the UI.
|
||||
|
||||
We might even take this a step further and place this logic within an `Object` that
|
||||
represents the `HtmlPage` we are currently on, as the following example shows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
public class CreateMessagePage {
|
||||
|
||||
@@ -111,8 +125,10 @@ represents the `HtmlPage` we are currently on, as the following example shows:
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
class CreateMessagePage(private val currentPage: HtmlPage) {
|
||||
|
||||
@@ -139,6 +155,7 @@ represents the `HtmlPage` we are currently on, as the following example shows:
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
Formerly, this pattern was known as the
|
||||
https://github.com/SeleniumHQ/selenium/wiki/PageObjects[Page Object Pattern]. While we
|
||||
@@ -154,8 +171,11 @@ includes a test dependency on `org.seleniumhq.selenium:selenium-htmlunit-driver`
|
||||
We can easily create a Selenium WebDriver that integrates with MockMvc by using the
|
||||
`MockMvcHtmlUnitDriverBuilder` as the following example shows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
WebDriver driver;
|
||||
|
||||
@@ -166,8 +186,10 @@ We can easily create a Selenium WebDriver that integrates with MockMvc by using
|
||||
.build();
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
lateinit var driver: WebDriver
|
||||
|
||||
@@ -178,6 +200,7 @@ We can easily create a Selenium WebDriver that integrates with MockMvc by using
|
||||
.build()
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
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`].
|
||||
@@ -195,35 +218,45 @@ application to a Servlet container. For example, we can request the view to crea
|
||||
message with the following:
|
||||
|
||||
--
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
CreateMessagePage page = CreateMessagePage.to(driver);
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
val page = CreateMessagePage.to(driver)
|
||||
----
|
||||
======
|
||||
--
|
||||
|
||||
We can then fill out the form and submit it to create a message, as follows:
|
||||
|
||||
--
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
ViewMessagePage viewMessagePage =
|
||||
page.createMessage(ViewMessagePage.class, expectedSummary, expectedText);
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
val viewMessagePage =
|
||||
page.createMessage(ViewMessagePage::class, expectedSummary, expectedText)
|
||||
----
|
||||
======
|
||||
--
|
||||
|
||||
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]
|
||||
@@ -233,8 +266,11 @@ with HtmlUnit, but it is much easier with WebDriver. Consider the following
|
||||
`CreateMessagePage` implementation:
|
||||
|
||||
--
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
public class CreateMessagePage extends AbstractPage { // <1>
|
||||
|
||||
@@ -262,6 +298,7 @@ with HtmlUnit, but it is much easier with WebDriver. Consider the following
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
<1> `CreateMessagePage` extends the `AbstractPage`. We do not go over the details of
|
||||
`AbstractPage`, but, in summary, it contains common functionality for all of our pages.
|
||||
For example, if our application has a navigational bar, global error messages, and other
|
||||
@@ -327,26 +364,35 @@ Finally, we can verify that a new message was created successfully. The followin
|
||||
assertions use the https://assertj.github.io/doc/[AssertJ] assertion library:
|
||||
|
||||
--
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
assertThat(viewMessagePage.getMessage()).isEqualTo(expectedMessage);
|
||||
assertThat(viewMessagePage.getSuccess()).isEqualTo("Successfully created a new message");
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
assertThat(viewMessagePage.message).isEqualTo(expectedMessage)
|
||||
assertThat(viewMessagePage.success).isEqualTo("Successfully created a new message")
|
||||
----
|
||||
======
|
||||
--
|
||||
|
||||
We can see that our `ViewMessagePage` lets us interact with our custom domain model. For
|
||||
example, it exposes a method that returns a `Message` object:
|
||||
|
||||
--
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
public Message getMessage() throws ParseException {
|
||||
Message message = new Message();
|
||||
@@ -357,11 +403,14 @@ example, it exposes a method that returns a `Message` object:
|
||||
return message;
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
fun getMessage() = Message(getId(), getCreated(), getSummary(), getText())
|
||||
----
|
||||
======
|
||||
--
|
||||
|
||||
We can then use the rich domain objects in our assertions.
|
||||
@@ -370,8 +419,11 @@ Lastly, we must not forget to close the `WebDriver` instance when the test is co
|
||||
as follows:
|
||||
|
||||
--
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
@AfterEach
|
||||
void destroy() {
|
||||
@@ -381,8 +433,9 @@ as follows:
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
@AfterEach
|
||||
fun destroy() {
|
||||
@@ -391,6 +444,7 @@ as follows:
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
--
|
||||
|
||||
For additional information on using WebDriver, see the Selenium
|
||||
@@ -403,8 +457,11 @@ In the examples so far, we have used `MockMvcHtmlUnitDriverBuilder` in the simpl
|
||||
possible, by building a `WebDriver` based on the `WebApplicationContext` loaded for us by
|
||||
the Spring TestContext Framework. This approach is repeated here, as follows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
WebDriver driver;
|
||||
|
||||
@@ -416,8 +473,9 @@ the Spring TestContext Framework. This approach is repeated here, as follows:
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
lateinit var driver: WebDriver
|
||||
|
||||
@@ -428,11 +486,15 @@ the Spring TestContext Framework. This approach is repeated here, as follows:
|
||||
.build()
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
We can also specify additional configuration options, as follows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
WebDriver driver;
|
||||
|
||||
@@ -449,8 +511,10 @@ We can also specify additional configuration options, as follows:
|
||||
.build();
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
lateinit var driver: WebDriver
|
||||
|
||||
@@ -467,12 +531,16 @@ We can also specify additional configuration options, as follows:
|
||||
.build()
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
As an alternative, we can perform the exact same setup by configuring the `MockMvc`
|
||||
instance separately and supplying it to the `MockMvcHtmlUnitDriverBuilder`, as follows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
MockMvc mockMvc = MockMvcBuilders
|
||||
.webAppContextSetup(context)
|
||||
@@ -489,11 +557,13 @@ instance separately and supplying it to the `MockMvcHtmlUnitDriverBuilder`, as f
|
||||
.build();
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
// Not possible in Kotlin until https://youtrack.jetbrains.com/issue/KT-22208 is fixed
|
||||
----
|
||||
======
|
||||
|
||||
This is more verbose, but, by building the `WebDriver` with a `MockMvc` instance, we have
|
||||
the full power of MockMvc at our fingertips.
|
||||
|
||||
@@ -8,8 +8,11 @@ supports paging through all messages. How would you go about testing it?
|
||||
|
||||
With Spring MVC Test, we can easily test if we are able to create a `Message`, as follows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
MockHttpServletRequestBuilder createMessage = post("/messages/")
|
||||
.param("summary", "Spring Rocks")
|
||||
@@ -19,8 +22,10 @@ With Spring MVC Test, we can easily test if we are able to create a `Message`, a
|
||||
.andExpect(status().is3xxRedirection())
|
||||
.andExpect(redirectedUrl("/messages/123"));
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
@Test
|
||||
fun test() {
|
||||
@@ -33,6 +38,7 @@ With Spring MVC Test, we can easily test if we are able to create a `Message`, a
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
What if we want to test the form view that lets us create the message? For example,
|
||||
assume our form looks like the following snippet:
|
||||
@@ -57,31 +63,39 @@ assume our form looks like the following snippet:
|
||||
How do we ensure that our form produce the correct request to create a new message? A
|
||||
naive attempt might resemble the following:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
mockMvc.perform(get("/messages/form"))
|
||||
.andExpect(xpath("//input[@name='summary']").exists())
|
||||
.andExpect(xpath("//textarea[@name='text']").exists());
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
mockMvc.get("/messages/form").andExpect {
|
||||
xpath("//input[@name='summary']") { exists() }
|
||||
xpath("//textarea[@name='text']") { exists() }
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
This test has some obvious drawbacks. If we update our controller to use the parameter
|
||||
`message` instead of `text`, our form test continues to pass, even though the HTML form
|
||||
is out of synch with the controller. To resolve this we can combine our two tests, as
|
||||
follows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[[spring-mvc-test-server-htmlunit-mock-mvc-test]]
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
String summaryParamName = "summary";
|
||||
String textParamName = "text";
|
||||
@@ -98,8 +112,9 @@ follows:
|
||||
.andExpect(redirectedUrl("/messages/123"));
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
val summaryParamName = "summary";
|
||||
val textParamName = "text";
|
||||
@@ -115,6 +130,7 @@ follows:
|
||||
redirectedUrl("/messages/123")
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
This would reduce the risk of our test incorrectly passing, but there are still some
|
||||
problems:
|
||||
|
||||
@@ -7,16 +7,20 @@ xref:testing/webtestclient.adoc#webtestclient-tests[Writing Tests] instead.
|
||||
|
||||
To perform requests that use any HTTP method, as the following example shows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
// static import of MockMvcRequestBuilders.*
|
||||
|
||||
mockMvc.perform(post("/hotels/{id}", 42).accept(MediaType.APPLICATION_JSON));
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
import org.springframework.test.web.servlet.post
|
||||
|
||||
@@ -24,19 +28,24 @@ To perform requests that use any HTTP method, as the following example shows:
|
||||
accept = MediaType.APPLICATION_JSON
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
You can also 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:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
mockMvc.perform(multipart("/doc").file("a1", "ABC".getBytes("UTF-8")));
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
import org.springframework.test.web.servlet.multipart
|
||||
|
||||
@@ -44,30 +53,42 @@ request. Rather, you have to set it up to be similar to the following example:
|
||||
file("a1", "ABC".toByteArray(charset("UTF8")))
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
You can specify query parameters in URI template style, as the following example shows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
mockMvc.perform(get("/hotels?thing={thing}", "somewhere"));
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
mockMvc.get("/hotels?thing={thing}", "somewhere")
|
||||
----
|
||||
======
|
||||
|
||||
You can also add Servlet request parameters that represent either query or form
|
||||
parameters, as the following example shows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
mockMvc.perform(get("/hotels").param("thing", "somewhere"));
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
import org.springframework.test.web.servlet.get
|
||||
|
||||
@@ -75,6 +96,7 @@ parameters, as the following example shows:
|
||||
param("thing", "somewhere")
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
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.
|
||||
@@ -87,13 +109,18 @@ request URI. If you must test with the full request URI, be sure to set the `con
|
||||
and `servletPath` accordingly so that request mappings work, as the following example
|
||||
shows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
mockMvc.perform(get("/app/main/hotels/{id}").contextPath("/app").servletPath("/main"))
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
import org.springframework.test.web.servlet.get
|
||||
|
||||
@@ -102,13 +129,17 @@ shows:
|
||||
servletPath = "/main"
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
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:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
class MyWebTests {
|
||||
|
||||
@@ -123,11 +154,14 @@ properties, as the following example shows:
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
// Not possible in Kotlin until https://youtrack.jetbrains.com/issue/KT-22208 is fixed
|
||||
----
|
||||
======
|
||||
|
||||
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
|
||||
|
||||
@@ -7,8 +7,11 @@ point to Spring configuration with Spring MVC and controller infrastructure in i
|
||||
|
||||
To set up MockMvc for testing a specific controller, use the following:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
class MyWebTests {
|
||||
|
||||
@@ -24,8 +27,9 @@ To set up MockMvc for testing a specific controller, use the following:
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
class MyWebTests {
|
||||
|
||||
@@ -40,6 +44,7 @@ To set up MockMvc for testing a specific controller, use the following:
|
||||
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
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
|
||||
@@ -47,8 +52,11 @@ as shown above.
|
||||
|
||||
To set up MockMvc through Spring configuration, use the following:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
@SpringJUnitWebConfig(locations = "my-servlet-context.xml")
|
||||
class MyWebTests {
|
||||
@@ -65,8 +73,9 @@ To set up MockMvc through Spring configuration, use the following:
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
@SpringJUnitWebConfig(locations = ["my-servlet-context.xml"])
|
||||
class MyWebTests {
|
||||
@@ -82,6 +91,7 @@ To set up MockMvc through Spring configuration, use the following:
|
||||
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
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
|
||||
@@ -108,8 +118,11 @@ a mock service with Mockito:
|
||||
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"]
|
||||
.Java
|
||||
----
|
||||
@SpringJUnitWebConfig(locations = "test-servlet-context.xml")
|
||||
class AccountTests {
|
||||
@@ -128,8 +141,10 @@ expectations, as the following example shows:
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
@SpringJUnitWebConfig(locations = ["test-servlet-context.xml"])
|
||||
class AccountTests {
|
||||
@@ -148,6 +163,7 @@ expectations, as the following example shows:
|
||||
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
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
|
||||
|
||||
@@ -6,8 +6,11 @@ some common and very useful features. For example, you can declare an `Accept` h
|
||||
all requests and expect a status of 200 as well as a `Content-Type` header in all
|
||||
responses, as follows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
// static import of MockMvcBuilders.standaloneSetup
|
||||
|
||||
@@ -18,19 +21,24 @@ responses, as follows:
|
||||
.build();
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
// Not possible in Kotlin until https://youtrack.jetbrains.com/issue/KT-22208 is fixed
|
||||
----
|
||||
======
|
||||
|
||||
In addition, third-party frameworks (and applications) can pre-package setup
|
||||
instructions, such as those in a `MockMvcConfigurer`. The Spring Framework has one such
|
||||
built-in implementation that helps to save and re-use the HTTP session across requests.
|
||||
You can use it as follows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
// static import of SharedHttpSessionConfigurer.sharedHttpSession
|
||||
|
||||
@@ -41,11 +49,13 @@ You can use it as follows:
|
||||
// Use mockMvc to perform requests...
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
// Not possible in Kotlin until https://youtrack.jetbrains.com/issue/KT-22208 is fixed
|
||||
----
|
||||
======
|
||||
|
||||
See the javadoc for
|
||||
{api-spring-framework}/test/web/servlet/setup/ConfigurableMockMvcBuilder.html[`ConfigurableMockMvcBuilder`]
|
||||
|
||||
@@ -5,8 +5,11 @@ The best way to test streaming responses such as Server-Sent Events is through t
|
||||
<<WebTestClient>> which can be used as a test client to connect to a `MockMvc` instance
|
||||
to perform tests on Spring MVC controllers without a running server. For example:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
WebTestClient client = MockMvcWebTestClient.bindToController(new SseController()).build();
|
||||
|
||||
@@ -26,6 +29,7 @@ to perform tests on Spring MVC controllers without a running server. For example
|
||||
.thenCancel()
|
||||
.verify();
|
||||
----
|
||||
======
|
||||
|
||||
`WebTestClient` can also connect to a live server and perform full end-to-end integration
|
||||
tests. This is also supported in Spring Boot where you can
|
||||
|
||||
Reference in New Issue
Block a user