[[spring-mvc-test-server-setup-options]]
= Setup Choices

MockMvc can be setup in one of two ways. One is to point directly to the controllers you
want to test and programmatically configure Spring MVC infrastructure. The second is to
point to Spring configuration with Spring MVC and controller infrastructure in it.

To set up MockMvc for testing a specific controller, use the following:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
	class MyWebTests {

		MockMvc mockMvc;

		@BeforeEach
		void setup() {
			this.mockMvc = MockMvcBuilders.standaloneSetup(new AccountController()).build();
		}

		// ...

	}
----

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
	class MyWebTests {

		lateinit var mockMvc : MockMvc

		@BeforeEach
		fun setup() {
			mockMvc = MockMvcBuilders.standaloneSetup(AccountController()).build()
		}

		// ...

	}
----
======

Or you can also use this setup when testing through the
xref:testing/webtestclient.adoc#webtestclient-controller-config[WebTestClient] which delegates to the same builder
as shown above.

To set up MockMvc through Spring configuration, use the following:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
	@SpringJUnitWebConfig(locations = "my-servlet-context.xml")
	class MyWebTests {

		MockMvc mockMvc;

		@BeforeEach
		void setup(WebApplicationContext wac) {
			this.mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
		}

		// ...

	}
----

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
	@SpringJUnitWebConfig(locations = ["my-servlet-context.xml"])
	class MyWebTests {

		lateinit var mockMvc: MockMvc

		@BeforeEach
		fun setup(wac: WebApplicationContext) {
			mockMvc = MockMvcBuilders.webAppContextSetup(wac).build()
		}

		// ...

	}
----
======

Or you can also use this setup when testing through the
xref:testing/webtestclient.adoc#webtestclient-context-config[WebTestClient] which delegates to the same builder
as shown above.



Which setup option should you use?

The `webAppContextSetup` loads your actual Spring MVC configuration, resulting in a more
complete integration test. Since the TestContext framework caches the loaded Spring
configuration, it helps keep tests running fast, even as you introduce more tests in your
test suite. Furthermore, you can inject mock services into controllers through Spring
configuration to remain focused on testing the web layer. The following example declares
a mock service with Mockito:

[source,xml,indent=0,subs="verbatim,quotes"]
----
	<bean id="accountService" class="org.mockito.Mockito" factory-method="mock">
		<constructor-arg value="org.example.AccountService"/>
	</bean>
----

You can then inject the mock service into the test to set up and verify your
expectations, as the following example shows:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
	@SpringJUnitWebConfig(locations = "test-servlet-context.xml")
	class AccountTests {

		@Autowired
		AccountService accountService;

		MockMvc mockMvc;

		@BeforeEach
		void setup(WebApplicationContext wac) {
			this.mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
		}

		// ...

	}
----

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
	@SpringJUnitWebConfig(locations = ["test-servlet-context.xml"])
	class AccountTests {

		@Autowired
		lateinit var accountService: AccountService

		lateinit var mockMvc: MockMvc

		@BeforeEach
		fun setup(wac: WebApplicationContext) {
			mockMvc = MockMvcBuilders.webAppContextSetup(wac).build()
		}

		// ...

	}
----
======

The `standaloneSetup`, on the other hand, is a little closer to a unit test. It tests one
controller at a time. You can manually inject the controller with mock dependencies, and
it does not involve loading Spring configuration. Such tests are more focused on style
and make it easier to see which controller is being tested, whether any specific Spring
MVC configuration is required to work, and so on. The `standaloneSetup` is also a very
convenient way to write ad-hoc tests to verify specific behavior or to debug an issue.

As with most "`integration versus unit testing`" debates, there is no right or wrong
answer. However, using the `standaloneSetup` does imply the need for additional
`webAppContextSetup` tests in order to verify your Spring MVC configuration.
Alternatively, you can write all your tests with `webAppContextSetup`, in order to always
test against your actual Spring MVC configuration.

