I am trying to create some unit tests for a service that I created in Java 11 using the java.net.http.HttpClient API.
The code works fine but I am getting java.lang.reflect.InaccessibleObjectException error when running the unit tests.
The Service 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
}
}
The test class is as follows:
@RunWith(MockitoJUnitRunner.class)
public class MyWebServiceTest {
@InjectMocks
private MyWebService service;
@Mock
private HttpClient httpClient;
@Test
public void shouldMakeHttpCallTest(){
service.makeHttpCall();
//asserts
}
}
Am I doing something wrong? I've seen that many people instantiate a new instance of the httpClient within the method itself, however, I am not sure if it is testable that way.
What I was trying to achieve is something like
@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());
}
}
Any help would be great. Thank you
The full stack trace is:
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)