SpringBoot2.7.5+Java11:JUnit5中Mock同步调用的WebClient
问题解决:SpringBoot测试中Autowired对象为空+Mock WebClient失败
问题原因分析
- 上下文加载范围错误:你在
@SpringBootTest中指定了classes = { Cicrawlrequesttrigger.class },如果这个类不是项目启动类,也未包含StockAvailibilityStrategy和WebClient配置类的扫描逻辑,Spring容器不会初始化这些Bean,自然@Autowired会返回空值。 - 注解混用错误:
- 要Mock Spring容器中的Bean,需用
@MockBean而非@Mock或@Autowired; @InjectMocks是Mockito用于将Mock对象注入目标类的注解,不能和@Autowired混用在同一字段上。
- 要Mock Spring容器中的Bean,需用
- 冗余注解:
@SpringBootTest已集成SpringExtension,无需额外添加@ExtendWith(SpringExtension.class)。
解决方案步骤
1. 修正测试类注解配置
- 要么去掉
classes属性,让@SpringBootTest加载项目启动类对应的完整上下文; - 要么指定包含
WebClient配置类和StockAvailibilityStrategy的类(比如项目启动类)。 - 用
@MockBean配合@Qualifier来Mock目标WebClient。
2. Mock WebClient调用逻辑
WebClient采用链式调用,需Mock它的get()/post()、uri()、retrieve()/exchange()等方法,而非直接Mock业务方法(比如你之前的Strategy.invokLoc)。
修正后的测试类示例
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) // 去掉classes限制,或指定项目启动类 @DirtiesContext @ActiveProfiles("test") public class StrategyTest { @Autowired private StockAvailibilityStrategy stockAvailibilityStrategy; @MockBean @Qualifier("kWebclient") private WebClient kWebclient; private Executor executor; @BeforeEach public void setUp() { executor = Executors.newFixedThreadPool(1); } @Test void testStrategyOptimise() { // 1. 构建Mock的WebClient响应 String mockResponse = "[{response}]"; // Mock WebClient的链式调用节点 WebClient.RequestHeadersUriSpec<?> requestHeadersUriSpec = Mockito.mock(WebClient.RequestHeadersUriSpec.class); WebClient.ResponseSpec responseSpec = Mockito.mock(WebClient.ResponseSpec.class); Mockito.when(kWebclient.get()).thenReturn(requestHeadersUriSpec); Mockito.when(requestHeadersUriSpec.uri(Mockito.anyString())).thenReturn(requestHeadersUriSpec); Mockito.when(requestHeadersUriSpec.retrieve()).thenReturn(responseSpec); Mockito.when(responseSpec.toEntity(String.class)) .thenReturn(Mono.just(new ResponseEntity<>(mockResponse, HttpStatus.OK))); // 2. 准备测试数据 CentralRepoLite central = getCentralRepoLite(); CReady cy = setTestCReady(); // 3. 执行测试方法 stockAvailibilityStrategy.optimise(testCRequest, StoreInfo, centralRepoEntities, cRepo, executor); // 4. 断言结果 assertNotNull(cy); } }
补充说明
- 如果
StockAvailibilityStrategy通过构造注入依赖WebClient,@MockBean会自动将Mock的WebClient注入到该Bean中,无需额外处理; - 若不需要完整Spring上下文,也可使用纯Mockito测试(
@ExtendWith(MockitoExtension.class)),此时用@InjectMocks注入StockAvailibilityStrategy,用@Mock创建WebClient的Mock对象,适合不需要其他Spring Bean的场景:
@ExtendWith(MockitoExtension.class) public class StrategyTest { @InjectMocks private StockAvailibilityStrategy stockAvailibilityStrategy; @Mock @Qualifier("kWebclient") private WebClient kWebclient; // ... 测试逻辑同上 }
内容的提问来源于stack exchange,提问作者Amulya M
相关产品推荐
相关产品推荐

