使用Mockito进行Java HttpClient单元测试

6ioyuze2  于 2022-11-08  发布在  Java
关注(0)|答案(2)|浏览(341)

我正在尝试使用java.net.http.HttpClient API为我在Java11中创建的服务创建一些单元测试。代码工作正常,但在运行单元测试时出现java.lang.reflect.InaccessibleObjectException错误。
服务类:

@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
    }
}

测试类如下:

@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)
public 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)
tjrkku2a

tjrkku2a1#

使用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);
r8xiu3jd

r8xiu3jd2#

这是因为HttpClient是一个抽象类。您应该使用CALLS_REAL_METHODS标记或模拟实现来模拟抽象类。
Here就是一个例子。
或者,您可以使用WireMock来模拟您调用的端点。Here示例

相关问题