6

I recently implemented simple JAX-RS REST endpoint. I'm wondering is there any transparent way of integration testing?

I searched a bit on stackowerflow and found these questions: first, second. They are a bit outdated and I hope there is already some better way of testing. The solutions proposed there don't solve my problem as they provide either vendor-specific or some complex third party ways.

Q: What is the modern way of testing JAX-RS services? Does Java EE provide solution for that? Or generally what is the best way of writing controller tests in Java EE ecosystem?

To be more specific I'm looking for some way that allows to easily test a REST call. In spring framework it usually looks like this:

@Autowired
MockMvc mvc;
@MockBean
MyService service;

@Test
public void shouldGetMyDto() {
    MyDto dto = new MyDto("test-id", "test-name");
    given(service.getMyDto("test-id")).willReturn(dto);

    mvc.perform(get("/api/my-entities/test-id"))
            .andExpect(status().isOk())
            .andExpect(content().contentType(APPLICATION_JSON_UTF8_VALUE))
            .andExpect(jsonPath("$.id", is("test-id")))
            .andExpect(jsonPath("$.name", is("test-name")));

    verify(service).getMyDto("test-id");
}
Sasha Shpota
  • 9,436
  • 14
  • 75
  • 148
  • Are you talking about unit tests or integration tests? Your example is a unit test. There is a an example of a pure JavaEE JAX-RS integration test at [jaxrs-people](https://github.com/sfcoy/jaxrs-people). – Steve C Nov 23 '17 at 22:13
  • 1
    @SteveC thank you for the hint, I'll use it for end-to-end tests. But it is not what I'm looking for right now. In your example you establish fully functional application run which I don't need. I just need to check that JAX-RS is integrated properly which means I need to check that the DTO gets converted to correct json, correct content type is being returned, status code is ok and correct service method is being called. Of course I don't need fully established service in this case - so I'd want to mock it somehow. That is what I'm looking for. – Sasha Shpota Nov 24 '17 at 08:00
  • What DI and REST frameworks do you use? – Justinas Jakavonis Nov 24 '17 at 11:41
  • @Justas I just generated default Wildfly Swarm project. I guess it uses Weld as CDI container and RESTEasy. – Sasha Shpota Nov 24 '17 at 11:48

1 Answers1

3

Arquillian and CDI Alternatives

For Java EE, you could use Arquillian to create micro deployments for your tests, allowing you to pick the classes you want to deploy. You can use CDI alternatives to provide a mock implementation for your services.

To add Maven dependencies to an Arquillian deployment, refer to this answer.

JAX-RS Client API and REST Assured

For testing the REST API itself, you can rely on the JAX-RS Client API, introduced in JAX-RS 2.0.

If you prefer a fluent API similar to what Spring provides, go for REST Assured.

Exploring other approaches

Depending on your needs regarding tests, you could also explore other solutions that do not use Java.

For example, Postman allows you to write test scripts. And it also provides Newman, to run the collections from the command line with Node.js.

Community
  • 1
  • 1
cassiomolin
  • 124,154
  • 35
  • 280
  • 359
  • [Here](https://github.com/cassiomolin/jersey-jwt/tree/master/src/test/java/com/cassiomolin/example) are some examples of tests with Arquillian using the JAX-RS Client API. – cassiomolin Nov 24 '17 at 12:21
  • [Here](https://github.com/cassiomolin/tasks-rest-api/tree/master/src/test/java/com/cassiomolin/example/task/api) are some examples with Spring Boot and REST Assured. I know you don't want to use Spring, but just have a look at what the tests look like. You can easily deploy the application with Arquillian and then target it with REST Assured. – cassiomolin Nov 24 '17 at 12:23
  • Thank you. I've just looked on the example from your first comment. It looks like this is what I need. But you don't mock service in `GreetingResourceTest ` so it probably loads full context. Is it possible to inject a mock instead of `GreetingService`? I want to test rest related code in isolation. Is it also possible to load only one endpoint in isolation? Let's say load `GreetingResource` without loading similar resources. I'd also like skipping loading of CDI beans that are not needed in my concrete resource. Is that possible? – Sasha Shpota Nov 24 '17 at 12:33
  • @OleksandrShpota Yes, all of it is possible with Arquillian and CDI. Arquillian allows you to pick the classes you want to deploy. And you can use CDI alternatives to provide a mock implementation for your services. – cassiomolin Nov 24 '17 at 13:01