Kong/unirest-java

MockResponse does not work with Unirest 4 anymore

timomeinen opened this issue · 7 comments

In the past I used this code to test a specific status code:

        client.expect(HttpMethod.POST)
                .thenReturn(MockResponse.of(500, "error"));

But this does not work anymore, as it gives this error with Jackson:

kong.unirest.core.UnirestException: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class kong.unirest.core.Headers and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: kong.unirest.core.MockResponse["headers"])

Here is a complete example:

public class ResponseTest {

    private MockClient client;

    @BeforeEach
    public void setUp() {
        client = MockClient.register();
        Unirest.config().setObjectMapper(new JacksonObjectMapper());
    }

    @Test
    void error() {
        client.expect(HttpMethod.POST)
                .thenReturn(MockResponse.of(500, "error"));

        // com.fasterxml.jackson.databind.exc.InvalidDefinitionException:
        // No serializer found for class kong.unirest.core.Headers and no properties discovered to create BeanSerializer
        // (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)
        // (through reference chain: kong.unirest.core.MockResponse["headers"])
        HttpResponse<String> response = Unirest.post("path").asString();

        assertEquals(500, response.getStatus());
        assertEquals("error", response.getBody());
    }

}

In the meanwhile I realized the api should be used like this:

client.expect(HttpMethod.POST)
        .thenReturn("error")
        .withStatus(500);

If MockResponse is for internal use only, maybe the visibility should be package-private iso public?

ryber commented

MockResponse is valid as a utility, people can use it in classes with methods that take a HttpResponse for example, it is not, as noted, intended to be used with the mock client.

You are not the first person to think this, and I think its reasonable to expect that if people think it should work some way, then maybe it should.

I'm intrigued that it EVER worked at least

Hi @ryber, I was not aware of that use case for MockResponse which makes sense. And I like the fluent API, too.

In fact, the response worked in Unirest 3. I just came around this problem when updating my source to Unirest 4 and suddenly the test failed.

ryber commented

I'm actually going to re-open this temporarily because I'm making it work again. but I'm having a maven central problem and have a ticket open with SonaType, I want to keep this open until I get it all resolved

ryber commented

ready to go in 4.0.7 @timomeinen

Tested it and it works again. Thank you @ryber. On the other side as I now know the fluent API I will use that one. ;-)

HI @ryber,

today I realized that the provided fix does not work correctly for the statusText:

            unirestMock.expect(HttpMethod.GET, HEALTH_URL)
                    .thenReturn(MockResponse.bad("Fail"));

            HttpResponse<Empty> response = Unirest.get(HEALTH_URL).asEmpty();
            assertThat(response.getStatus()).isEqualTo(400);
            assertThat(response.getStatusText()).isEqualTo("bad request"); // FAIL: No statustext

But using the fluent API works as expected:

            unirestMock.expect(HttpMethod.GET, HEALTH_URL)
                    .thenReturn("Fail")
                    .withStatus(400, "bad request");

Although the kong.unirest.core.MockResponse does set a statustext:

public static <T> MockResponse<T> bad(T body) {
    return new MockResponse<>(400, "bad request", body);
}
ryber commented

@timomeinen fixed in 4.1.1