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.