如何在@Autowired注入的Bean中使用Mockito实现依赖Mock
问题场景
示例基于Spring Boot与Mockito框架实现,测试类初始代码如下:
class MyTestClass{ @Autowired MyController myController; @Test void testMethod(){ Actor actor = myController.getActorOverHTTP(); // 该方法内部依赖需要Mock myController.someStaff(actor); } }
getActorOverHTTP方法内部调用了httpClient的方法,httpClient是标注@Service注解的Spring托管Bean:
return httpClient.requestActor();
需要实现的效果:MockHttpClient实例,调用requestActor()时直接返回预设的模拟Actor对象,不触发真实HTTP请求。
实现方案
根据你写的是集成测试还是纯单元测试,选对应写法即可:
写法1:Spring Boot集成测试(最常用,启动Spring上下文)
用Spring Boot自带的@MockBean注解,直接把Spring容器里原生的HttpClient Bean替换为Mock对象,所有注入HttpClient的位置都会自动使用这个Mock实例:
import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import static org.mockito.Mockito.when; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.times; @SpringBootTest class MyTestClass{ @Autowired MyController myController; // 替换容器中原有HttpClient Bean为Mock对象 @MockBean HttpClient httpClient; @Test void testMethod(){ // 构造你需要的预设返回对象 Actor mockActor = new Actor(); mockActor.setId(1L); mockActor.setName("test_actor"); // 定义Mock规则:调用requestActor()时直接返回预设对象,不执行真实逻辑 when(httpClient.requestActor()).thenReturn(mockActor); // 调用业务方法,内部拿到的就是你预设的mockActor Actor actor = myController.getActorOverHTTP(); myController.someStaff(actor); // 可选:验证requestActor()确实被调用了1次 verify(httpClient, times(1)).requestActor(); } }
如果需要模拟请求异常场景,直接把规则改成:
when(httpClient.requestActor()).thenThrow(new RuntimeException("模拟HTTP请求超时"));
写法2:纯单元测试(不启动Spring容器,执行速度更快)
如果不需要加载整个Spring上下文,只做MyController的单元测试,用Mockito原生的@Mock+@InjectMocks组合即可:
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import static org.mockito.Mockito.when; // 启用Mockito注解支持 @ExtendWith(MockitoExtension.class) class MyTestClass{ // 自动把@Mock生成的模拟对象注入到该实例中 @InjectMocks MyController myController; // 生成HttpClient的Mock实例 @Mock HttpClient httpClient; @Test void testMethod(){ Actor mockActor = new Actor(); when(httpClient.requestActor()).thenReturn(mockActor); Actor actor = myController.getActorOverHTTP(); myController.someStaff(actor); } }
注意事项
- 要保证Mock的类类型和代码中注入的
HttpClient类型完全一致,否则会出现Mock不生效、依然调用真实方法的问题。 - 如果
requestActor()方法带参数,定义规则时要匹配参数,比如用any()匹配任意入参,或者传入具体值做精确匹配。
内容的提问来源于stack exchange,提问作者Tristate
相关产品推荐
相关产品推荐

