繁体   English   中英

Java HttpClient 单元测试与 Mockito

[英]Java HttpClient unit testing with Mockito

嗨,想知道是否有人可以帮助我。 我正在尝试使用 java.net.http.HttpClient API 为我在 Java 11 中创建的服务创建一些单元测试。 代码工作正常,但运行单元测试时出现 java.lang.reflect.InaccessibleObjectException 错误。

服务 class `

@Stateless
public class MyWebService {

    @Inject
    private HttpClient httpClient;

    public void makeHttpCall(){

        final HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://someurl.com"))
            .headers(CONTENT_TYPE, "application/json")
            .GET()
            .build();

        final HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());

      // business logic
    }
}

`

测试class如下

@RunWith(MockitoJUnitRunner.class)
public class MyWebServiceTest {

    @InjectMocks
    private MyWebService service;

    @Mock
    private HttpClient httpClient;

    @Test
    public void shouldMakeHttpCallTest(){

        service.makeHttpCall();
        
        //asserts
    }
}

我做错了吗? 我已经看到很多人在方法本身中实例化了一个新的 httpClient 实例,但是我不确定它是否可以通过这种方式进行测试。

我试图实现的是

@RunWith(MockitoJUnitRunner.class)

公共 class JdkHttpClientServiceShould {

@InjectMocks
private JdkHttpClientService victim;
@Mock
private HttpClient httpClient;

@Test
@SuppressWarnings({"unchecked", "rawtypes"})
public void executeRequest() throws Exception {
    HttpResponse httpResponse = mock(HttpResponse.class);
    when(httpClient.send(any(HttpRequest.class), any(HttpResponse.BodyHandler.class))).thenReturn(httpResponse);
    when(httpResponse.statusCode()).thenReturn(200);
    when(httpResponse.body()).thenReturn("Hello");

    ArgumentCaptor<HttpRequest> httpRequestArgumentCaptor = ArgumentCaptor.forClass(HttpRequest.class);
    ArgumentCaptor<HttpResponse.BodyHandler<String>> bodyHandlerArgumentCaptor = ArgumentCaptor.forClass(HttpResponse.BodyHandler.class);

    ClientResponse clientResponse = victim.executeRequest(HTTP_URL);

    assertThat(clientResponse.getStatusCode()).isEqualTo(200);
    assertThat(clientResponse.getResponseBody()).isEqualTo("Hello");

    verify(httpClient, times(1)).send(httpRequestArgumentCaptor.capture(), bodyHandlerArgumentCaptor.capture());
    assertThat(httpRequestArgumentCaptor.getValue().uri().toString()).isEqualTo(HTTP_URL);
    assertThat(httpRequestArgumentCaptor.getValue().method()).isEqualTo(GET_METHOD);
    assertThat(httpRequestArgumentCaptor.getValue().headers().map()).containsExactly(Assertions.entry(HEADER_KEY_CLIENT_TYPE, Collections.singletonList(JDK_HTTP_CLIENT.getValue())));
    assertThat(bodyHandlerArgumentCaptor.getValue()).isEqualTo(HttpResponse.BodyHandlers.ofString());
}

}

任何帮助都会很棒。 谢谢

完整的堆栈跟踪是

java.lang.reflect.InaccessibleObjectException: Unable to make protected java.net.http.HttpClient() accessible: module java.net.http does not "opens java.net.http" to unnamed module @595b007d

    at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:340)
    at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:280)
    at java.base/java.lang.reflect.Constructor.checkCanSetAccessible(Constructor.java:189)
    at java.base/java.lang.reflect.Constructor.setAccessible(Constructor.java:182)
    at org.mockito.internal.creation.cglib.ClassImposterizer.setConstructorsAccessible(ClassImposterizer.java:86)
    at org.mockito.internal.creation.cglib.ClassImposterizer.imposterise(ClassImposterizer.java:56)
    at org.mockito.internal.creation.cglib.ClassImposterizer.imposterise(ClassImposterizer.java:49)
    at org.mockito.internal.creation.cglib.CglibMockMaker.createMock(CglibMockMaker.java:24)
    at org.mockito.internal.util.MockUtil.createMock(MockUtil.java:33)
    at org.mockito.internal.MockitoCore.mock(MockitoCore.java:59)
    at org.mockito.Mockito.mock(Mockito.java:1285)
    at org.mockito.internal.configuration.MockAnnotationProcessor.process(MockAnnotationProcessor.java:33)
    at org.mockito.internal.configuration.MockAnnotationProcessor.process(MockAnnotationProcessor.java:16)
    at org.mockito.internal.configuration.DefaultAnnotationEngine.createMockFor(DefaultAnnotationEngine.java:43)
    at org.mockito.internal.configuration.DefaultAnnotationEngine.process(DefaultAnnotationEngine.java:66)
    at org.mockito.internal.configuration.InjectingAnnotationEngine.processIndependentAnnotations(InjectingAnnotationEngine.java:71)
    at org.mockito.internal.configuration.InjectingAnnotationEngine.process(InjectingAnnotationEngine.java:55)
    at org.mockito.MockitoAnnotations.initMocks(MockitoAnnotations.java:108)
    at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl$1.withBefores(JUnit45AndHigherRunnerImpl.java:27)
    at org.junit.runners.BlockJUnit4ClassRunner.methodBlock(BlockJUnit4ClassRunner.java:319)
    at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
    at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
    at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
    at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
    at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:221)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)

这是因为HttpClient是一个抽象的 class。 您应该使用CALLS_REAL_METHODS标记或模拟实现来模拟抽象 class 。

是一个例子。

或者你可以使用WireMock来模仿你调用的端点。 这里的例子

使用 mockito @Spy

@ExtendWith(MockitoExtension.class) // using junit5


@Mock 
HttpResponse<InputStream> mockResponse;

@Spy 
HttpClient httpClient;

void test() throws Exception {
  when(httpClient.send(any(), any(HttpResponse.BodyHandlers.ofInputStream().getClass())))
    .thenReturn(mockResponse);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM