Search code examples
javaunit-testingjunitmockitojooby

Joobie: How to properly unit test a route that returns different content depending on MediaType?


I am currently experimenting with writing webapps/apis using Jooby. I have it set up with an endpoint that returns account data, either as HTML or as JSON depending on the accept header value. This endpoint works and returns the correct information.

When writing unit tests in JUnit, how do I pass an accept header value along with my get request so that I can test what is returned from the request properly?

I have tried using Mockito to mock a Request object and return responses to various calls to the request object but I can't seem to find in the documentation how Jooby tests for the header values within it's own Request object when you use the Results.when method.

This is my endpoint:

get("/allAccounts", () ->
   Results
          .when(MediaType.html, () -> Results.html("display").put("accounts", accounts))
          .when(MediaType.json, () -> accounts)
          .when("*", () -> Status.NOT_ACCEPTABLE)
);

Tests tried so far have all been similar to the following. I have tried many difference methods in place of 'type()' such as .accept() but none seem to be queried as the MockRouter's get() method never returns a string under any of these conditions

@Test
public void allAccountsHTMLunitTest() throws Throwable {

    Request req = mock(Request.class);
    when(req.type()).thenReturn(MediaType.html);

    String result = new MockRouter(new App(), req)
        .get("/allAccounts");

    assertEquals(// some assertion );
}

I am expecting (perhaps wrongly) that when I make a get request via the MockRouter with the header either "accept: text/html" or "accept: application/json" that it should return a string containing html or json respectively.

Instead I get an error that I'm trying to cast a Result object to a String.

Am I seriously misunderstanding this?


Solution

  • That's correct and it is basically the difference between unit and integration tests.

    For unit tests all MockRouter does is to invoke the route handler function, the function /allAccounts returns a Result object that is why you got a class cast exception.

    Here your example but using the Result accessing the value via result.get()

      @Test
      public void allAccountsHTMLunitTest() throws Throwable {
    
        Request req = mock(Request.class);
        when(req.type()).thenReturn(MediaType.html);
    
        Result result = new MockRouter(new App(), req)
            .get("/allAccounts");
    
        View view = result.get();
        assertEquals("display", view.name());
        assertEquals("{accounts=[1, 2]}", view.model().toString());
    
      }
    

    Hopes this helps.