Spring Boot中如何使用Mockito对RestTemplateBuilder构建的RestTemplate做Mock
Mock RestTemplate返回响应的实现方案
你可以通过Mockito测试框架完成Mock,以下两种方案可根据你的测试场景选择:
方案1:纯单元测试(无需启动Spring上下文,执行效率高)
核心思路:用Mockito模拟所有外部依赖,不加载Spring容器,直接对目标方法做单元测试。
测试代码示例
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 org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.web.client.RestTemplate; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.*; import static org.junit.jupiter.api.Assertions.*; @ExtendWith(MockitoExtension.class) public class TestConsumerTest { @Mock private RestTemplateBuilder restTemplateBuilder; @Mock private RestTemplate restTemplate; @Mock private AccountService accountService; @InjectMocks private TestConsumer testConsumer; @Test public void testAdminAccountGet() { // 1. 打桩RestTemplateBuilder的链式调用,返回mock的RestTemplate when(restTemplateBuilder.basicAuthentication(anyString(), anyString())) .thenReturn(restTemplateBuilder); when(restTemplateBuilder.rootUri(anyString())) .thenReturn(restTemplateBuilder); when(restTemplateBuilder.build()).thenReturn(restTemplate); // 2. 模拟accountService返回Admin类型的账户 Account mockAdmin = new Account(); mockAdmin.setType("Admin"); when(accountService.getAccount()).thenReturn(mockAdmin); // 3. 模拟restTemplate调用AAA路径的返回值 when(restTemplate.getForObject(eq("AAA"), eq(String.class))).thenReturn("admin response"); // 4. 执行测试方法,断言结果 String result = testConsumer.testGet(); assertEquals("admin response", result); // 验证确实调用了AAA路径的接口 verify(restTemplate, times(1)).getForObject(eq("AAA"), eq(String.class)); } @Test public void testNormalAccountGet() { // 同上先打桩RestTemplateBuilder when(restTemplateBuilder.basicAuthentication(anyString(), anyString())) .thenReturn(restTemplateBuilder); when(restTemplateBuilder.rootUri(anyString())) .thenReturn(restTemplateBuilder); when(restTemplateBuilder.build()).thenReturn(restTemplate); // 模拟返回普通账户 Account mockNormal = new Account(); mockNormal.setType("Normal"); when(accountService.getAccount()).thenReturn(mockNormal); // 模拟调用BBB路径的返回 when(restTemplate.getForObject(eq("BBB"), eq(String.class))).thenReturn("normal response"); String result = testConsumer.testGet(); assertEquals("normal response", result); verify(restTemplate, times(1)).getForObject(eq("BBB"), eq(String.class)); } }
方案2:Spring Boot集成测试(启动Spring上下文,适合需要依赖Spring容器能力的场景)
如果你需要在Spring环境下测试,可以用@MockBean注解替换Spring容器中的真实Bean,无需修改原有业务代码:
测试代码示例
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.client.RestTemplate; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.when; import static org.junit.jupiter.api.Assertions.assertEquals; @SpringBootTest public class TestConsumerSpringTest { @Autowired private TestConsumer testConsumer; @MockBean private AccountService accountService; @MockBean private RestTemplate restTemplate; // 如果是用RestTemplateBuilder构建的RestTemplate,也可以直接Mock RestTemplateBuilder的返回 // @MockBean // private RestTemplateBuilder restTemplateBuilder; // @BeforeEach // public void setup() { // when(restTemplateBuilder.basicAuthentication(anyString(), anyString())) // .thenReturn(restTemplateBuilder); // when(restTemplateBuilder.rootUri(anyString())) // .thenReturn(restTemplateBuilder); // when(restTemplateBuilder.build()).thenReturn(restTemplate); // } @Test public void testAdminGet() { Account mockAdmin = new Account(); mockAdmin.setType("Admin"); when(accountService.getAccount()).thenReturn(mockAdmin); when(restTemplate.getForObject(eq("AAA"), eq(String.class))).thenReturn("spring test admin response"); String result = testConsumer.testGet(); assertEquals("spring test admin response", result); } }
内容的提问来源于stack exchange,提问作者tony
相关产品推荐
相关产品推荐

