如何使用 RestTemplate 和 JUnit 测试 restclient?

Posted

技术标签:

【中文标题】如何使用 RestTemplate 和 JUnit 测试 restclient?【英文标题】:How to test restclient using RestTemplate and JUnit? 【发布时间】:2019-11-22 14:03:27 【问题描述】:

我是 JUNIT 的新手,使用 RestTemplate 调用我的服务,我收到了 200 条响应。但是,我无法使用 JUnit 测试该类。尝试了不同的方法并获得 400 和 404。我想发布请求正文(json)并测试状态。如果有任何问题,请告诉我。

/**
* Rest client implementation
**/  
public class CreateEmailDelegate implements CDM 
         
    @Autowired
    private RestTemplate restTemplate;
    private  String url = "http://example.com/communications/emails";
        
    public ResponseEntity<CDResponse> createEmail(CDMEmailRequest cDRequest) throws UnavailableServiceException, InvalidInputException 
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.set("SR_API_Key", SR_API_KEY);
        httpHeaders.set("consumerIdentification", CONSUMER_IDENTIFICATION);
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);         
        HttpEntity< CDMEmailRequest > cDRequestEntity = new HttpEntity<>( cDRequest, httpHeaders);  
        ResponseEntity< CDResponse > cDResponse = null;
                
        try 
            cDResponse = restTemplate.postForEntity(url, cDRequestEntity, CDResponse.class);
         catch (Exception e) 
            LOGGER.error(e.getMessage());
            throw  e;       
        
                
        return cDResponse;
    
  

我的测试类返回 404 状态而不是 200

    @RunWith(SpringJUnit4ClassRunner.class)
    public class CreateEmailCommunicationDelegateTest 
    
        @Before
        public void setup() 
            httpHeaders = new HttpHeaders();
            httpHeaders.set("SR_API_Key", SR_API_KEY);
            httpHeaders.set("consumerIdentification", CONSUMER_IDENTIFICATION);
            httpHeaders.setContentType(MediaType.APPLICATION_JSON);
            DefaultMockMvcBuilder builder = MockMvcBuilders.webAppContextSetup(this.wac);
            this.mockMvc = builder.build();
        
    
    
        public void testResponse() throws Exception, HttpClientErrorException, JsonProcessingException 
            String url = "http://example.com/CommunicationDeliveryManagement-Service-1.0.0/communications/emails";
    
            CDMEmailRequest anObject = new CDMEmailRequest();
            ResultMatcher ok = MockMvcResultMatchers.status().isOk();
            ObjectMapper mapper = new ObjectMapper();
            mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, false);
            ObjectWriter ow = mapper.writer().withDefaultPrettyPrinter();
            String requestJson = ow.writeValueAsString(anObject);
    
            System.out.println(requestJson);
            MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.post(url).contentType(MediaType.APPLICATION_JSON_UTF8).content(requestJson);
            this.mockMvc.perform(builder).andExpect(ok).andDo(MockMvcResultHandlers.print());
        
     

 

我的测试类使用 TestRestTemplate 而不是 MockMvc 返回 400

@RunWith(SpringJUnit4ClassRunner.class)
public class CreateEmailCommunicationDelegateTest 

    @Before
    public void setup() 
        httpHeaders = new HttpHeaders();
        // rest headers as above
    

    @Test
    public void testResponse() throws Exception, HttpClientErrorException, JsonProcessingException 

        String url = "http://example.com/CommunicationDeliveryManagement-Service-1.0.0/communications/emails";

        String username = "";
        String password = "";
        HttpEntity<CDMEmailRequest>
                cDEntity = new HttpEntity<>(httpHeaders);

        restTemplate = new TestRestTemplate(username, password);

        responseEntity =
                restTemplate.exchange(url, HttpMethod.POST, cDEntity,
                        CDResponse.class);

        assertNotNull(responseEntity);
        assertEquals(HttpStatus.OK,
                responseEntity.getStatusCode());
    
 

【问题讨论】:

请正确格式化您的代码。我看到你在使用 Mockito Runner,你也用 mockito 标记了这个问题,但我没有在代码中看到任何与 mockito 的交互。 已删除,谢谢 是外部服务吗? 对,就是休息服务 您不能使用 MockMvc 或 TestRestTemplate 进行 Restclients 测试,请参阅我的答案 【参考方案1】:

我认为您正在尝试实现集成测试而不是单元测试,这是有很大区别的。 MockMvc 应该用于实现单元测试,TestRestTemplate 应该用于集成测试。您既不能使用它来测试客户端实现。

见Unit and Integration Tests in Spring Boot

如果您正在使用 Spring Boot,则可以使用另一种方法来实现您的目标,请参阅此问题 Spring boot testing of a rest client using @RestClientTest。

【讨论】:

感谢您的回复。是的,我正在尝试仅进行集成测试(Springboot)。我将按照您提到的示例进行检查。 @susan 如果答案可以帮助您解决问题,请投票

以上是关于如何使用 RestTemplate 和 JUnit 测试 restclient?的主要内容,如果未能解决你的问题,请参考以下文章

集成测试中 MockMvc 和 RestTemplate 的区别

RestTemplate GET 请求抛出 400 Bad Request

如何使用 spring 记录 RestTemplate 请求和响应?

如何为 Rest 模板编写 Mockito Junit 测试用例?

如何使用带有Json主体和标头的RestTemplate进行POST调用? [重复]

Spring Boot:如何使用 WebClient 而不是 RestTemplate 来执行非阻塞和异步调用