Reputation: 335
I've been trying to mock Java 11's HttpClient but I've been having trouble. This is what I have so far:
public class ApiPokerTest {
HttpClient client = mock(HttpClient.class);
@Test
public void poking_api_returns_list_of_modules() throws Exception {
HttpResponse<String> resp = mock(HttpResponse.class);
when(resp.body()).thenReturn("Hello world");
when(client.send(any(), any())).thenReturn(resp);
}
}
This doesn't work because any() doesn't match HttpResponse type. All I want is when the client calls send() it returns a mocked response with given JSON. How can I do this?
Upvotes: 1
Views: 3744
Reputation: 30273
For some reason this took me over an hour to figure out, trying all sorts of solutions on Stack Overflow. In the end @ezer's answer helped me, and I didn't even have to use @Spy.
I simply mocked these 2 things:
@ExtendWith(MockitoExtension.class)
public class MyTest {
@Mock HttpResponse<String> response;
@Mock HttpClient httpClient;
...
And I made sure sendAsync
returns the mocked response:
when(httpClient.sendAsync(any(), any(HttpResponse.BodyHandlers.ofString().getClass())))
.thenReturn(CompletableFuture.completedFuture(response));
And finally made the mocked response return what I wanted. I only cared about the body:
when(response.body()).thenReturn("A mocked response!");
I think the key I was missing was the HttpResponse.BodyHandlers.ofString().getClass()
. Before, I kept getting errors because the second parameter of sendAsync
is a generic, T. I think specifying the class that way resolved the generic parameter issue.
Upvotes: 1
Reputation: 1172
use 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);
// ...
}
Upvotes: 1
Reputation: 609
Mockito
can't mock final
classes (HttpClientImpl is such class) out of the box. Use Spock
and its MockingApi
. With this testing framework you can write test case like this:
given:
def client = Mock(HttpClient)
when:
def response = Mock(HttpResponse)
def responseBody = { 'Hello world' } as Supplier<String>
1 * response.body() >> responseBody
1 * client.send(_ as HttpRequest, _ as HttpResponse.BodyHandler) >> response
def mockedResponseBody = client.send(HttpRequest.newBuilder()
.uri(new URI('http://localhost:8080'))
.build(), HttpResponse.BodyHandlers.discarding()).body()
then:
mockedResponseBody.get() == responseBody.get()
If you insist using Mockito you have to add mocito-extensions
directory in test\resources
with org.mockito.plugins.MockMaker
file with line mock-maker-inline
inside.
Upvotes: 0