Francesco
Francesco

Reputation: 1792

Mocking a http response using vert.x rxjava2 and Mockito

I'm playing with the rxjava vert.x (ver. 3.8.4) WebClient. My client will call some services so, by Mockito (ver. 3.2.4) I'm testing how it should handle an error. Here is how I mock the service's response:

...
JsonObject jsonResponse = new JsonObject();
HttpResponse<Buffer> httpResponse = Mockito.mock(HttpResponse.class);
Mockito.when(httpResponse.statusCode()).thenReturn(500);
Mockito.when(httpResponse.bodyAsJsonObject()).thenReturn(jsonResponse);
HttpRequest<Buffer> httpRequest = Mockito.mock(HttpRequest.class);
Mockito.when(httpRequest.rxSend()).thenReturn(Single.just(httpResponse));
return httpRequest;
...

as the Mockito.when(httpResponse.statusCode()).thenReturn(500); is executed I get this error:

org.mockito.exceptions.misusing.UnfinishedStubbingException: 
Unfinished stubbing detected here:
-> at my.dummy.project.ServiceHandlerTest.serviceRepliesWithA500Response(ServiceHandlerTest.java:70)

E.g. thenReturn() may be missing.
Examples of correct stubbing:
    when(mock.isOk()).thenReturn(true);
    when(mock.isOk()).thenThrow(exception);
    doThrow(exception).when(mock).someVoidMethod();
Hints:
 1. missing thenReturn()
 2. you are trying to stub a final method, which is not supported
 3. you are stubbing the behaviour of another mock inside before 'thenReturn' instruction is completed
...

What am I missing here?

Upvotes: 3

Views: 3009

Answers (1)

Erunafailaro
Erunafailaro

Reputation: 1959

My advice would be to use okhttp's MockWebServer for this kind of test case.

MockWebserver can be instantiated for each test and will allow you to create a webservice url that can be used by your implementation under test to send a real http request against it.

Before that you can define a mock response that will be returned by the mockwebserver to your implementation.

I don't know your test case, but this snippet should make clear how MockWebServer works.

More examples and the full docu can be found at their github repo.

As you can see below, you can make a couple of assertions, eg. if the correct request method has been used, how many requests were fired and if the correct request parameters and body were used during the request.

    @ExtendWith(VertxExtension.class)
    @Slf4j
    public class WebServiceTest {

        private WebServiceRequester sut;

        private MockWebServer mockWebServer;

        @BeforeEach
        public void setUp() {
            sut = new WebServiceRequester();
            mockWebServer = new MockWebServer();
        }

        @Test
        public void testCallService(final Vertx vertx, final VertxTestContext testContext) throws InterruptedException {
            // given
            final JsonObject requestPayload = new JsonObject().put("requestData", new JsonArray("[]"));
            final JsonObject serverResponsePayload = new JsonObject().put("responseData", new JsonArray("[]"));
            mockWebServer.enqueue(new MockResponse()
                                      .setBody(serverResponsePayload.encode())
                                      .setResponseCode(200)
                                      .setHeader("content-type", "application/json"));

            // when
            final String webServiceUrl = mockWebServer.url("/").toString();
            final Promise<String> stringPromise =
                sut.callService(
                    webServiceUrl,
                    requestPayload,
                    vertx);

            // then
            final RecordedRequest recordedRequest = mockWebServer.takeRequest();
            assertEquals("POST", recordedRequest.getMethod());
            assertEquals("[text={\"request\":[]}]", recordedRequest.getBody().toString());
            assertEquals(1, mockWebServer.getRequestCount());
            testContext.assertComplete(stringPromise.future())
                       .map(val -> {
                           assertEquals("promise_completed", val);
                           testContext.completeNow();
                           return val;
                       })
                       .onComplete(onComplete -> {
                           assertTrue(onComplete.succeeded());
                           log.info("done");
                       })
                       .onFailure(onError -> Assertions.fail());

        }
    }

Upvotes: 2

Related Questions