【问题标题】:How to mock HttpClient's send method in junit 5?如何在junit 5中模拟HttpClient的发送方法?
【发布时间】:2021-10-29 12:31:28
【问题描述】:

我正在使用 HttpClient 实例的 send() 方法调用外部服务。

public class MyProgram {
    
    
    private String producerEndpoint;
    private HttpClient httpClient;
    
    
    @Autowired
    public EsignEventProducer(@Value("${producer.http.endpoint}")String producerEndpoint) {
        this.producerEndpoint=producerEndpoint;
        this.httpClient=HttpClient.newBuilder().build();
    }
    
    public void sendMessage(ObjectMapper objectMapper, String jsonString, String xCorrelationId) throws Exception {

        ProduceRequest produceRequest=new ProduceRequest();
        ProduceRecord produceRecord=new ProduceRecord();
        produceRecord.setValue(Optional.of(objectMapper.readTree(jsonString)));
        produceRequest.setRecords(Arrays.asList(produceRecord));
        
        HttpRequest request=HttpRequest.newBuilder()
                .uri(URI.create(producerEndpoint))
                .POST(HttpRequest.BodyPublishers.ofString(objectMapper.writeValueAsString(produceRequest)))
                .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON.toString())
                .setHeader(IdTypeConstants.XCORRELATIONID, xCorrelationId)
                .build();
        
        httpClient.send(request, HttpResponse.BodyHandlers.ofString());
    }
}

在创建 Junit 测试用例时,我正在模拟 httpClient.send(request, HttpResponse.BodyHandlers.ofString());,如下所示,但仍然不是模拟,而是调用实际方法。 以下是 Junit 测试类。

class MyProgramTest {
    
    @InjectMocks
    private MyEventProducer myEventProducer;
    
    private HttpClient httpClient;
    private HttpResponse<Object> httpResponse;
    
    @Mock
    private HttpRequest request;
    
    private MyEvent schema;
    
    @BeforeEach
    void setUp() {
        MockitoAnnotations.initMocks(this);
        schema = new MyEvent();
        schema.setId("123");
        schema.setName("PACKAGE_COMPLETE");
        schema.setCreatedDate("2021-10-20T16:17:58.408Z");
        schema.setSessionUser("dummySession");
        httpClient = Mockito.mock(HttpClient.class);
        httpResponse = Mockito.mock(HttpResponse.class);
    }
    
    @Test
    void testSendMessage() throws Exception {
        ReflectionTestUtils.setField(myEventProducer, "producerEndpoint", "http://localhost:8080/endpointservice/my_topic");
        ObjectMapper objectMapper = new ObjectMapper();
        String jsonString = objectMapper.writeValueAsString(schema);
        String xCorrelationId = "dummyXCorrelationId";
        Mockito.when(httpClient.send(Mockito.any(HttpRequest.class), HttpResponse.BodyHandlers.ofString())).thenReturn(null);
        myEventProducer.sendMessage(objectMapper, jsonString, xCorrelationId);
        verify(httpClient).send(request, HttpResponse.BodyHandlers.ofString());
    }
}

我在 java.net 包中使用带有 gradle 和 httpClient 的 Junit 5。 请帮忙,谢谢

【问题讨论】:

  • 您应该将您的测试类添加到您的问题中。您是否将您的 httpClient 定义为 Mock,例如 HttpClient httpClient = Mockito.mock(HttpClient.class)
  • 嗨@TheFrozenOne,我已经添加了测试类,谢谢

标签: java mockito httpclient junit5


【解决方案1】:

问题在于EsignEventProducer 构造函数创建了一个新的HttpClient,而不是使用模拟。相反,应该将 HttpClient 实例传递给构造函数。

@Autowired
public EsignEventProducer(@Value("${producer.http.endpoint}") String producerEndpoint, HttpClient httpClient) {
    this.producerEndpoint = producerEndpoint;
    this.httpClient = httpClient;
}

【讨论】:

    【解决方案2】:

    您的测试中有几件事混淆了,我会坚持使用一种类型的模拟创建,无论是通过注释还是显式。 正如蒂姆摩尔所说,主要问题是您的模拟没有注入。 您在httpClient = Mockito.mock(HttpClient.class); 之前调用MockitoAnnotations.initMocks(this);,因此不会注入您的HttpClient 模拟。最简单的方法是像这样注释 httpClient 字段:

    @Mock
    private HttpClient httpClient;
    

    并在您的设置方法中删除显式的Mockito.mock(HttpClient.class); 调用。 所以整个班级会是这样的:

    class MyProgramTest {
    
    @InjectMocks
    private MyEventProducer myEventProducer;
    
    @Mock
    private HttpClient httpClient;
    @Mock
    private HttpResponse<Object> httpResponse;
    
    @Mock
    private HttpRequest request;
    
    private MyEvent schema;
    
    @BeforeEach
    void setUp() {
        MockitoAnnotations.initMocks(this);
        schema = new MyEvent();
        schema.setId("123");
        schema.setName("PACKAGE_COMPLETE");
        schema.setCreatedDate("2021-10-20T16:17:58.408Z");
        schema.setSessionUser("dummySession");
    }
    
    @Test
    void testSendMessage() throws Exception {
        ReflectionTestUtils.setField(myEventProducer, "producerEndpoint",    "http://localhost:8080/endpointservice/my_topic");
        ObjectMapper objectMapper = new ObjectMapper();
        String jsonString = objectMapper.writeValueAsString(schema);
        String xCorrelationId = "dummyXCorrelationId";
        Mockito.when(httpClient.send(Mockito.any(HttpRequest.class), HttpResponse.BodyHandlers.ofString())).thenReturn(null);
        myEventProducer.sendMessage(objectMapper, jsonString, xCorrelationId);
        verify(httpClient).send(request, HttpResponse.BodyHandlers.ofString());
    }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-04
      • 1970-01-01
      相关资源
      最近更新 更多