如何使用@WebMvcTest 春季测试在模拟服务中注入模拟的restTemplate

Posted

技术标签:

【中文标题】如何使用@WebMvcTest 春季测试在模拟服务中注入模拟的restTemplate【英文标题】:How to inject mocked restTemplate in moked service with @WebMvcTest spring test 【发布时间】:2022-01-23 22:10:40 【问题描述】:

我正在尝试使用 @WebMvcTest 并使用 @MockBean 模拟我的服务,并注入要模拟的 restTemplate var (junit5)。

如何在服务模拟中使用 bean 配置以及如何在模拟服务中模拟 restTemplate var? 我需要从已经创建配置的服务中限定restTemplate

Bean配置类

@Configuration
public class RestTemplateConfig 
    @Bean
    public RestTemplate restTemplate()
        return new RestTemplate();
    

服务类

@Service
public class MyService 

    // restTemplate is coming null on tests
    @Autowired
    private RestTemplate restTemplate;

    public ResponseEntity<Object> useRestTemplate() 
       
            return restTemplate.exchange(
                        "url", 
                        HttpMethod.POST,
                        new HttpEntity<>("..."), 
                        Object.class);
         
    

测试类

@WebMvcTest(controllers = MyController.class)
class MyControllerTest 

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private MyService myService;

    @MockBean
    private RestTemplate restTemplate;


    @Test
    void test() throws Exception
    
        when(gatewayRestService.useRestTemplate()).thenCallRealMethod();
    
        when(
             restTemplate.exchange(
                 anySring(),
                 eq(HttpMethod.POST),
                 any(HttpEntity.class),
                 eq(Object.class)
             )
        ).thenReturn(ResponseEntity.ok().body("..."));
    
        mockMvc.perform(
                    post("/path")
                    .content("...")
                    .header("Content-Type", "application/json")
                )
                .andExpect(status().isOk() );
    

我尝试在MyControllerTest 上使用@Import(RestTemplateConfig.class) 但没有成功,restTemplate 在服务测试中继续为空

【问题讨论】:

【参考方案1】:

为什么要模拟 RestTemplate@WebMvcTest 用于创建仅关注 Spring MVC 组件的 Spring MVC 测试,这意味着您的 MyController 仅。如果您想对MyService 进行单元测试,您应该只打扰嘲笑RestTemplate,事实并非如此。

话虽如此,你只需要模拟MyService如下:

@WebMvcTest(controllers = MyController.class)
class MyControllerTest 

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private MyService myService;

    @Test
    void test() throws Exception 
        when(myService.useRestTemplate()).thenReturn(ResponseEntity.ok().body("..."));
    
        mockMvc.perform(
                    post("/path")
                    .content("...")
                    .header("Content-Type", "application/json")
                )
                .andExpect(status().isOk() );
    

【讨论】:

以上是关于如何使用@WebMvcTest 春季测试在模拟服务中注入模拟的restTemplate的主要内容,如果未能解决你的问题,请参考以下文章

@WebMvcTest 在 Spring Boot 测试中为不同服务提供“Error Creating bean with name”错误

@WebMvcTest 可以有两个控制器吗

如何在@WebMvcTest 测试中忽略@EnableWebSecurity 注释类

在春季启动测试中使用wiremock随机端口设置属性

如何在 MockMVC 中模拟一些 bean 而不是其他的?

如何将 bean 加载到测试上下文中?