Now that spring 2.6.x supports WebTestClient
in MCV environments, it could be worth switching from MockMvc
to WebTestClient
.
Could somebody advise why tests with WebTestClient
are significant slower than MockMvc
?
Example
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.util.StopWatch;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringBootTest
@AutoConfigureMockMvc
class MyMockMvcTests {
@Test
void testWithMockMvc(@Autowired MockMvc mvc) throws Exception {
StopWatch w = new StopWatch();
w.start();
mvc.perform(get("/")).andExpect(status().isOk()).andExpect(content().string("Hello World"));
w.stop();
System.out.println("MockMvc: " + w.getTotalTimeMillis() + "ms");
}
// If Spring WebFlux is on the classpath, you can drive MVC tests with a WebTestClient
@Test
void testWithWebTestClient(@Autowired WebTestClient webClient) {
StopWatch w = new StopWatch();
w.start();
webClient
.get().uri("/")
.exchange()
.expectStatus().isOk()
.expectBody(String.class).isEqualTo("Hello World");
w.stop();
System.out.println("WebTestClient: " + w.getTotalTimeMillis() + "ms");
}
@TestConfiguration
static class TestServletConfig {
@RestController
class ExceptionTestServlet {
@GetMapping("/")
public String noContent() {
return "Hello World";
}
}
}
}
Output
WebTestClient: 46ms
MockMvc: 2ms
That's almost x20 execution time for WebTestClient
. But why?
And more important: could this be optimized, maybe in a future release?
Or is this due to the nature of WebTestClient
, and nothing can be done about it?
Comment From: bclozel
Could this be an initialization issue?
Maybe the first test will trigger initialization of the web infrastructure a pay a cost that the other won't have to?
Maybe there's an initialization cost bound to WebTestClient
that you only pay once per JVM?
Could you check if the x20 figure holds in case of multiple tests and different ordering of execution?
Comment From: membersound
Thanks for the suggestion.
Indeed when copying the tests multiple times, always only one of the mcv/client tests has such a huge execution delay. All subsequent tests are then around 1ms!
So your guess is correct, it is probably an initialization issue.