WebTestClient注入失败求助:Spring WebFlux集成测试Mock依赖
Hey there! I totally get that navigating Spring's testing annotations can feel overwhelming when you're new to the stack—let's work through your problem step by step.
First, let's break down what's going wrong with your current setup:
- Using
@SpringBootTestwith specific classes tries to spin up a partial context, but yourClientdepends onHttpServletRequest, which isn't automatically provided in that setup, leading to the unsatisfied dependency error. - Mixing
@TestConfigurationwith@SpringBootTestcauses configuration conflicts because they're competing to define the test context. - When you tried
@WebFluxTest, it didn't load yourSomeServiceby default (since it only focuses on web-layer beans), which is why yourClientwas null.
Here's the fix to get your deep mocking working without loading the full context:
1. Use @WebFluxTest for focused web controller testing
This annotation is designed exactly for testing WebFlux controllers—it only loads beans related to the web layer, which keeps your test context lightweight. We'll explicitly import your SomeService so it's available for the controller, and use @MockBean to replace the real Client.
2. Correctly mock the Client to return a fake WebClient
Instead of pointing the mocked WebClient to a real external URL, we'll configure it to return your expected response directly, so no external requests are made at all.
Updated Test Code:
import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; import org.springframework.http.HttpStatus; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.reactive.server.WebTestClient; import org.springframework.web.reactive.function.client.ClientResponse; import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; import static org.mockito.Mockito.when; @RunWith(SpringRunner.class) @WebFluxTest(SomeController.class) // Focus only on this controller @Import(SomeService.class) // Import the service your controller depends on public class SomeControllerTest { @Autowired private WebTestClient webTestClient; @MockBean private Client client; // Mock the deep dependency @Before public void setUp() { // Create a mock WebClient that returns your expected response WebClient mockWebClient = WebClient.builder() .exchangeFunction(request -> Mono.just(ClientResponse.create(HttpStatus.OK) .body("201 Created") .build()) ) .build(); // Make the mocked Client return this fake WebClient when(client.build()).thenReturn(mockWebClient); } @Test public void deepMocking() { webTestClient.get() .uri("/endpoint") .exchange() .expectStatus().isOk() .expectBody(String.class).isEqualTo("201 Created"); } }
Why this works:
@WebFluxTestloads only the web-related beans (like yourSomeController) and auto-configuresWebTestClientfor you.@Import(SomeService.class)tells Spring to create an instance ofSomeServicefor the test. Since we've mockedClientwith@MockBean, Spring will inject this mock intoSomeServiceinstead of the real one.- The mocked
WebClientuses a customexchangeFunctionto return your expected "201 Created" response directly, so no external HTTP calls are ever made.
Bonus Notes:
- You don't need
@AutoConfigureWebTestClientwith@WebFluxTest—it's already included. - Avoid mixing
@SpringBootTestwith@WebFluxTestunless you specifically need a full context (which you don't here). - If your
Clienthad more complex dependencies, you could mock those too, but in this case, since we're replacing the entireClientwith a mock, we don't need to worry about itsHttpServletRequestdependency at all.
Content of the question comes from Stack Exchange, question author Krotz

