RestClient and Mockito/PowerMockito

1,611 views
Skip to first unread message

John Somers

unread,
Feb 5, 2021, 12:47:06 PM2/5/21
to MicroProfile
Hi guys,

how do you mock a RestClient class with Mockito for unit testing?

For example, I have an interface which has REST annotations which a web service class implements and I call the web service through that interface in a rest client object e.g.

Client code
Service.class
protected IResource getResource() {
    URI apiURI = new URI(ApplicationProperties.getResourceURI());
    IResource resource = RestClientBuilder.newBuilder().baseUri(apiURI).build(IResource.class);
}

IResource resource = this.getResource();
Response response = resource.getSomething(id);
if (response.getStatus() != Response.Status.OK.getStatusCode()) {
throw new Exception("Could not retrieve resource");
}

In my ServiceTest.class I have:
@InjectMocks
private Service service;

IResource mock = Mockito.mock(IResource.class);
PowerMockito.mockStatic(ApplicationProperties.class);
PowerMockito.when(ApplicationProperties.getResourceURI()).thenReturn("http://host/resource-context");
Service spy = PowerMockito.spy(service);
PowerMockito.doReturn(mock).when(service, "getResource");

Getting this error though:
java.lang.NullPointerException
at org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl.addAnswersForStubbing(PowerMockitoStubberImpl.java:66)
at org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl.prepareForStubbing(PowerMockitoStubberImpl.java:129)
at org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl.when(PowerMockitoStubberImpl.java:94)

i.e. it's still getting through to the IResource resource = RestClientBuilder.newBuilder().baseUri(apiURI).build(IResource.class); line

I've also tried mocking up the RestClient and while this works, it doesn't appear to work if there are 2 different web resources to go out to:

private IResource createMockWebService() {
String uriString = "http://host/resource-root";
final URI uri = URI.create(uriString);
PowerMockito.mockStatic(ApplicationProperties.class);
PowerMockito.when(ApplicationProperties.getResourceURI()).thenReturn(uriString);
PowerMockito.mockStatic(RestClientBuilder.class);
RestClientBuilder restClientBuilderNewBuilder = Mockito.mock(RestClientBuilder.class);
PowerMockito.when(RestClientBuilder.newBuilder()).thenReturn(restClientBuilderNewBuilder);
RestClientBuilder restClientBuilderBaseURI = Mockito.mock(RestClientBuilder.class);
Mockito.when(restClientBuilderNewBuilder.baseUri(uri)).thenReturn(restClientBuilderBaseURI);
IResource resource = Mockito.mock(IResource.class);
Mockito.when(restClientBuilderBaseURI.build(IResource.class)).thenReturn(resource);
return resource;
}

Andy McCright

unread,
Feb 5, 2021, 3:08:14 PM2/5/21
to MicroProfile
Hi,

You will probably need to mock the RestClientBuilder instance in order for it to return a mocked instance of IResource.  You could refactor your client code so that you either pass in the builder or acquire it from a method that you could intercept and mock - or you could mock the RestClientBuilderResolver SPI class.

When you call RestClientBuilder.newBuilder(), the builder class calls the instance() method of the RestClientBuilderResolver class.  Before invoking the newBuilder() method, you could set the instance of the resolver to a mocked version that returns a mocked builder when it's newBuilder() method is called.  From there, your mocked builder could return the mocked version of IResource.  

Hope this helps,

Andy

Reply all
Reply to author
Forward
0 new messages