SteveSt
SteveSt

Reputation: 1297

Call a Rest method with mockito

I use Jersey and I have the following Rest function which returns a JSON string when my server is deployed:

@GET
@Path("getallemployees")
@Produces("application/json")
public Response getAllEmployees() {
//building the entity object which is List<Employee>
return Response.ok(entity).build();
}

I need to develop some unit tests (not integration testing) and I want to somehow mock the HTTPRequest that invokes this method and then get the json String. The best option would be to use mockito for this.

Is there any suggestion on how to do it ?

Thanks !!

Upvotes: 2

Views: 3704

Answers (2)

Lee Meador
Lee Meador

Reputation: 12985

The problem is that the method returns a Response object to the caller which is deep within the framework code. It doesn't return JSON strings.

You can use Mockito, if you need to mock something inside the method itself. That should work.

But you may need to take the value returned by the method and convert it to JSON like this if you are using Jackson with Jersey.

Response response = getAllEmployees();
Object retval = response.getEntity();
try {
    ObjectMapper mapper = new ObjectMapper();
    // I like this formatting. You can change it.
    mapper.configure(Feature.INDENT_OUTPUT, true);
    mapper.configure(Feature.WRITE_ENUMS_USING_TO_STRING, true);
    mapper.configure(Feature.USE_ANNOTATIONS, false);
    mapper.configure(Feature.FAIL_ON_EMPTY_BEANS, false);
    mapper.setSerializationInclusion(Inclusion.NON_NULL);
    mapper.getSerializationConfig().setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
    mapper.getSerializationConfig().withSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
    String json = mapper.writeValueAsString(retval);
    ... assert something about the string
} catch (JsonProcessingException e) {
    // do something
} catch (IOException e) {
    // do something
}

Upvotes: 1

Jonathan
Jonathan

Reputation: 20375

Some of this is guess work and speculation on my part but it may help. You could try using the Jersey Test Framework with the InMemoryTestContainerFactory:

It starts Jersey application and directly calls internal APIs to handle request created by client provided by test framework. There is no network communication involved. This containers does not support servlet and other container dependent features, but it is a perfect choice for simple unit tests.

It looks like to use it, all you need to do is extend JerseyTest and then override getTestContainerFactory() and follow the rest of the instructions, e.g.:

public class EmployeeResourceTest extends JerseyTest {
    @Override
    protected Application configure() {
        // set up employee resource with mock dependencies etc...
        return new ResourceConfig().registerInstances(employeeResource);
    }

    @Test
    public void getAllEmployees() {
        final String response = target("getallemployees").request().get(String.class);
        // assert etc...
    }
}

I used registerInstances instead of registerClasses in configure() as it looks like you can present a ready made Resource but set up with any mock dependencies you may want - although I haven't tried this myself.

The test class is a bit inflexible as you can only do one-time set up of dependencies in the configure() method, so it might be worth investigating using the MockitoJUnitRunner - although I'm not sure if it will work with the JerseyTest inheritance. It could allow you to do add behaviour to mocks in each @Test method, e.g.:

    @Mock
    private EmployeeResourceDependency dependency;

    @InjectMocks
    private EmployeeResource employeeResource;

    // configure() as above but without mock setup up etc...

    @Test
    public void getAllEmployees() {
        given(dependency.getEmployees()).willReturn(...); 

        // etc...

But like I said it might not be possible to mix them at all.

Upvotes: 1

Related Questions