Testing REST web services using spring

If you are not all in with test driven development and you built your spring @Controllers before writing a test, find out in this screencast two methods for testing your rest endpoint by using spring mvc test framework.

Detailed Video Notes

With the release of spring framework 3.2 came some powerful techniques to writing controller tests by performing request and receiving responses without having to deploy application code to a web container. Including the spring-test allows you to mock up a HttpServletRequest and validate the JSON that is returned in the HttpServletResponse.

There are two ways to approach testing while both are considered a form of an integration tests that focus on verifying the behaviors within the controllers and output of the response. First is to load your entire spring context using webAppContextSetUp and the second is a lighter approach using standAloneConfig. Let's examine each approach.

Project set up

[0:39]

Visiting spring initializer website and selecting web project dependency we will create a spring boot skeleton project. Adding JsonPath as an additional project dependency will allow us to validate JSON being returned by a controller.

<dependency>
    <groupId>com.jayway.jsonpath</groupId>
    <artifactId>json-path</artifactId>
    <version>1.2.0</version>
</dependency>

Getting started

[0:52]

Creating a class called Address and an associated AddressController we will mock up data then expose a URL /address that returns JSON. Let's fire up our server and validate our set up by making a request using postman. Alternatively you could of used advanced rest client. Be sure to check out our tutorial how to make a GET request with jquery and spring if you are looking more detail.

Address class

public class Address {
    
    private String street;
    private String state;

    //...
}

Controller class

@RestController
public class AddressController {

    @RequestMapping(value = "/address", 
        method = RequestMethod.GET, 
        produces = "application/json")
    public Address getAddress() {

        Address address = new Address();
        address.setState("FL");
        address.setStreet("12345 Horton Ave");

        return address;
    }
}

JSON output

{
    "street": "12345 Horton Ave",
    "state": "FL"
}

Using webAppContextSetUp

[1:8]

The first approach will load your entire spring context which will create necessary beans and dependencies to inject into your @Controller class. By going this route you inherently validate the java or xml configuration within your application. Spring boot by default creates a class ApplicationTests that will load applicationContext so we will extend it and create a class TestUsingWebAppContextSetUp.

At this point there is two important classes to be aware of. First is WebApplicationContext which extends the familiar ApplicationContext which offers easy access to spring attributes from a web application. Second is MockMvc which is a specific class to write service side test for spring MVC applications. We will initialize MockMvc with the Web ApplicationContext that we autowired into our class.

Next we will write our test. In our example we want to validate three things:

  1. When making a request to the url will return a status of OK or HTTP 200
  2. The content type of the response is application/json
  3. The value of the JSON street attribute equals to "12345 Horton Ave"

Writing out test we can use various methods from the mockMVC class that will simulate the request without having a dependency on a server such as apache tomcat, websphere, jetty or even glassfish. Now lets run out test and validate we are green.

public class TestUsingWebAppContextSetUp extends ApplicationTests {

    @Autowired
    private WebApplicationContext webApplicationContext;

    private MockMvc mockMvc;

    @Before
    public void setup() {
        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
                .build();
    }

    @Test
    public void validate_get_address() throws Exception {

        mockMvc.perform(get("/address"))
                .andExpect(status().isOk())
                .andExpect(
                        content().contentType(MediaType.APPLICATION_JSON_VALUE))
                .andExpect(jsonPath("$.street").value("12345 Horton Ave"));

    }

}

Using standaloneSetup

[2:26]

The second approach using standaloneSetup is lighter and closer to writing a unit test using a mocking framework like mockito. We will create a new class named TestUsingStandaloneSetup. The key difference from TestUsingWebAppContextSetUp is that we will create MockMVC by registering the AddressController and configuring Spring MVC infrastructure programmatically which will skip loading your entire context either with javaconfig or xml config. This will set up the minimal classes necessary while also giving us more control. We will copy the same test used in our prior example and run our test.

public class TestUsingStandaloneSetup {

    private final MockMvc mockMvc = standaloneSetup(new AddressController())
            .build();

    @Test
    public void validate_get_address() throws Exception {

        mockMvc.perform(get("/address"))
                .andExpect(status().isOk())
                .andExpect(
                        content().contentType(MediaType.APPLICATION_JSON_VALUE))
                .andExpect(jsonPath("$.street").value("12345 Horton Ave"));
    }
}

[3:1]

There is a lot more to testing spring controllers in REST application such as mocking filters, security and your domain dependencies. Hopefully this tutorial outlined the two ways to get started testing your applications that should you to explore some more of the advanced techniques.

Thanks for joining in today's level up, have a great day!