Tag Archives: java

Spring MVC integration test with REST Assured and MockMvc

Spring controllers can provide a lot of functionality and in most applications I have seen the web layer code is scattered among java code, annotations and XML config files. Even in the simplest controllers there is a lot that can go wrong – there are request mappings and methods, returned content type, response body, request parameters and calls to services in the layer below. I have always wondered what is the best way to test it all together? Obviously you can get the application up and running in order to execute acceptance tests (headless or via a browser) but this can be a bit of an overkill. Another option is to write a unit test but then arguably you would test the controller out of the context (but you may still want to do this anyway).

Ideally, you would have a test which does not require running a servlet container (memory requirements, start-up time, extra dependencies and good old faff to set it up) and enables testing all functionality (code and meta-code). We want an integration test which will not be limited to a simple Java class (fed with mock HTTP servlet request/response) but will go through the DispatcherServlet and enable us to work with HTTP requests and responses so that we test what is actually produced by our application.

In version 3.2 Spring introduced MockMvc which is a huge improvement and enables us to easily implement this type of tests. When combined with REST Assured (“Java DSL for easy testing of REST services”) we get to use fluent API (including given, when, then) to create code that is expressive as well as easy to read and understand.

Let’s take a look at a ‘hello world’ controller and method:

@RequestMapping(value = "/hello", 
                method = RequestMethod.GET, 
                produces = "application/json;charset=UTF-8")
public @ResponseBody String hello(
            @RequestParam(required = false, 
                defaultValue = "world") String name) {
    return format("Hello {0}!", name);
}

Not much code but emotions are high – we map all GET requests to ‘hello’ url to this method and return JSON content. We can take an optional String parameter called ‘name’, should it not be included in the request we will use “world” value. So how do I test it?

@Test public void 
getHello() {
    given().
    when().
        get(HELLO).
    then().
        statusCode(HttpServletResponse.SC_OK).
        contentType("application/json").
        body(equalTo("Hello world!"));
}  

@Test public void 
getHelloWithParam() {
    given().
        param("name", "coder").
    when().
        get(HELLO).
    then().
        statusCode(HttpServletResponse.SC_OK).
        contentType("application/json").
        body(equalTo("Hello coder!"));
}

Also, we can test that POST method is not supported:

@Test public void
failPostToHello() {
    given().
    when().
        post(HELLO).
    then().
        statusCode(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
}

Now let’s have a look at the test setup:

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(
        "classpath:test-mvc-dispatcher-servlet.xml")
public class HelloControllerTest {
    
    private MockMvc mockMvc;
    
    @Autowired
    private WebApplicationContext context;
    
    @Before
    public void setUp() {
        mockMvc = MockMvcBuilders
                .webAppContextSetup(context).build();
        RestAssuredMockMvc.mockMvc = mockMvc;
    }
    ...	
}

The ContextConfiguration annotation tells Spring about the location of the config file (test-mvc-dispatcher-servlet.xml) which allows for configuration of the WebApplicationContext which, thanks to WebAppConfiguration annotation, gets auto-wired in the context variable which is used to build mockMvc. To quote the javadoc MockMvc is “main entry point for server-side Spring MVC test support”, basically it encapsulates all your web configuration and makes it available to the test. Note that I modified the context configuration so component scan is limited to controllers only (web package) and I can mock the other beans using Mockito.

<context:component-scan 
        base-package="com.czeczotka.spring.web"/>

<mvc:annotation-driven />

<bean id="newsService" 
        class="org.mockito.Mockito" factory-method="mock">
    <constructor-arg 
        value="com.czeczotka.spring.service.NewsService" />
</bean>

Let’s discuss something a little bit more useful. How about testing controller’s interaction with services as well as the response body (which is a slightly more complicated this time)? I created a simple News class (String headline; String article; LocalDateTime timestamp) and a controller to return the latest news. I think this is where REST Assured and MockMvc combined shine – I can set up controllers interactions with the service using Mockito and still test http response. Note the fully qualified import of Mockito’s org.mockito.Mockito.when() method.

@Test public void
getLatestNews() {
    LocalDateTime dateTime = LocalDateTime.now ();
    String now = formatter.format (dateTime);
    org.mockito.Mockito.
        when (newsService.getLatestNews ()).
        thenReturn (new News ("Some news!", 
                    "These are some news!", dateTime));

    given ().
    when ().
        get (LATEST).
    then ().
        statusCode (HttpServletResponse.SC_OK).
        contentType ("application/json").
        body ("headline",  equalTo ("Some news!")).
        body ("article",   equalTo ("These are some news!")).
        body ("timestamp", equalTo (now));
}

@Test public void
getLatestNewsWithSeveralResults () {
    int number = 3;
    LocalDateTime dateTime = LocalDateTime.now ();
    String now = formatter.format (dateTime);
    org.mockito.Mockito.
        when (newsService.getLatestNews (number)).
        thenReturn (Arrays.asList (
            new News ("Some news! 0", 
                "These are some news! 0", dateTime),
            new News ("Some news! 1", "
                These are some news! 1", dateTime),
            new News ("Some news! 2", 
                "These are some news! 2", dateTime)
        ));

    given ().
    when ().
        get (LATEST + "/" + number).
    then ().
        statusCode (HttpServletResponse.SC_OK).
        contentType ("application/json").
        body ("size()", equalTo (number)).
        body ("[0].headline",  equalTo ("Some news! 0")).
        body ("[0].article",   
                    equalTo ("These are some news! 0")).
        body ("[0].timestamp", equalTo (now)).
        body ("[1].headline",  equalTo ("Some news! 1")).
        body ("[1].article",   
                    equalTo ("These are some news! 1")).
        body ("[1].timestamp", equalTo (now)).
        body ("[2].headline",  equalTo ("Some news! 2")).
        body ("[2].article",   
                    equalTo ("These are some news! 2")).
        body ("[2].timestamp", equalTo (now));
}

We can ask for some logging information, in the example we can log all or only some elements of the request/response such as params, body, headers, cookies, method or path. There is also an option to log on failed validation (log().ifValidationFails()):

@Test public void
getHelloWithLogging() {
    given ().
        log().all ().
    when ().
        get (HELLO).
    then ().
        log().all ().
        statusCode (HttpServletResponse.SC_OK);
}

I hope you found it helpful, to me the MockMvc and REST Assured combo definitely changes the way I think about testing Spring controllers and gives me much more confidence in the final solution.

The code

The code of this post is on github so follow the link below to browse it.

http://github.com/czeczotka/spring-mvc-integration-test

You can easily clone and play with it locally by simply following these steps.

$ git clone https://github.com/czeczotka/spring-mvc-integration-test.git
$ cd spring-mvc-integration-test
$ mvn test

Links

JUnit rules!

Apologies for the shouty title, I couldn’t stop myself. In JUnit 4.7 a new feature was introduced – rules. They enable us to modify how test methods are executed to provide more flexible and powerful tests. I think the name was chosen so that people would have to search for “junit rules” and google trends seem to (weakly) support this theory. In your face TestNG!

google-trends-for-junit-rules
Google Trends for “junit rules” search term

The functionality is implemented by annotating a field (of class TestRule or MethodRule) with the @Rule annotation.

This is a quick tour of the most useful rules.

What’s your name again?

Would you like to know your test method’s name while executing it? Simple, use TestName.

@Rule
public TestName name = new TestName();

@Test
public void printTestMethodName() {
    System.out.println(
        "Test method name: " + name.getMethodName());
}
Test method name: printTestMethodName

We want quick tests!

Quick as in “not slow”. Let’s say you need to deal with a class full of badly written integration tests, each of which unnecessarily taking several seconds to run. Bad bad panda. You can set up a timeout (Timeout) in your test class which will fail lengthy tests (just note you’re dealing with milliseconds). Another good thing is that it will actually interrupt the test execution thread so your test method will be time-boxed by the timeout.

@Rule
public Timeout timeout = new Timeout(20);

@Test
public void slowTestAskingForTrouble() throws InterruptedException {
    Thread.sleep(1000 * 60);
}
java.lang.Exception: test timed out after 20 milliseconds

Exceptions expected

Sometimes you want to check if an exception is thrown. You can do it without the rules but then you can’t check for the message.

@Test(expected = IllegalArgumentException.class)
public void exceptionExpected(){
    throw new IllegalArgumentException("catch me if you can");
}

Exception messages are important. Sometimes they can tell the whole story, i.e. would you prefer to simply catch UserNotFoundException or would you also like to see the message “Can not load user with id ‘null'” in the production log? Right, let’s check for the exception message with ExpectedException.

@Rule
public ExpectedException thrown = ExpectedException.none();

@Test
public void exceptionWithMessageExpected(){
    thrown.expect(IllegalArgumentException.class);
    thrown.expectMessage("catch me if you can");
    throw new IllegalArgumentException("catch me if you can");
}

This rule is initialised with ExpectedException.none() as by default we don’t expect methods to end up with an exception. We state this behaviour as per method basis.

Note that you can use Timeout and ExpectedException together and have a passing test

@Test
public void slowTestWithExpectedException()
         throws InterruptedException {
    thrown.expect(Exception.class);
    thrown.expectMessage(
        "test timed out after 20 milliseconds");
    Thread.sleep(1000 * 60);
}

Collect your errors (all of them)

Sometimes you end up having several assertions to verify that the returned object is ok. Let’s say you load a user object and the first assertion is for user’s first name and it fails. Fix it, run again to discover that the date of birth assertion fails too. Repeat to discover that their work phone number is empty (who uses these anyway?)… Wouldn’t it be nice to find out all failing assertions after the first execution? This is when ErrorCollector comes in silver armour and on a white horse to rescue the situation.

@Rule
public ErrorCollector collector = new ErrorCollector();

@Test
public void errorCollectorExample() {
    collector.addError(
        new Throwable("trouble here"));
    collector.addError(
        new Throwable("trouble there"));
    collector.addError(
        new Throwable("trouble everywhere"));
}
java.lang.Throwable: trouble here
	at com.czeczotka.junit.JUnitRulesTest.errorCollectorExample(JUnitRulesTest.java:52)

java.lang.Throwable: trouble there
	at com.czeczotka.junit.JUnitRulesTest.errorCollectorExample(JUnitRulesTest.java:53)

java.lang.Throwable: trouble everywhere
	at com.czeczotka.junit.JUnitRulesTest.errorCollectorExample(JUnitRulesTest.java:54)

Watch your tests

Should you be interested in being able to get you hands on test’s lifecycle events you can use TestWatcher. It will not let you change the test but you can register callbacks for different events such as failed, finished, skipped, starting, succeeded. Useful for reporting or if you wanted to take some extra actions, i.e. feedback the problem to you continuous delivery pipeline.

private static StringBuilder report = new StringBuilder();

@Rule
public TestWatcher watcher = new TestWatcher() {
    @Override
    protected void failed(Throwable e, Description description) {
        report.append("  FAILURE: ").append(
            description.getMethodName()).append("\n");
    }

    @Override
    protected void succeeded(Description description) {
        report.append("  Success: ").append(
            description.getMethodName()).append("\n");
    }
};

@AfterClass
public static void tearDownClass() {
    System.out.println("@AfterClass report");
    System.out.println(report.toString ());
}
@AfterClass report
    Success: exceptionExpected
    Success: printTestMethodName
    FAILURE: errorCollectorExample
    Success: slowTestWithExpectedException
    Success: exceptionWithMessageExpected
    FAILURE: slowTestAskingForTrouble

Other useful stuff

  • TemporaryFolder – enables you to create files and directories (newFile(), newFolder() methods) that will be removed after test execution
  • ExternalResource – useful to access an external resource such as a database or ssh connection (methods before() and after()) but I think I’d prefer to use BeforeClass and AfterClass annotations to do the job
  • Verifier – to potentially fail a test which would otherwise be successful after some extra assertions, i.e.: temporary folder was too big (in conjunction with TemporaryFolder rule)

The code

The code of this post is on github so follow the link below to browse it. Note that it contains failing tests to demonstrate presented ideas.

http://github.com/czeczotka/junit-rules

You can easily clone and play with it locally by simply following these steps.

$ git clone https://github.com/czeczotka/junit-rules.git
$ cd junit-rules
$ mvn test

Links

Writing Cucumber JVM step definitions

When I started working with Cucumber JVM it took a while to get the knack of how to write nice and efficient step definitions. Being a regular expression ninja certainly helps but you can get by with a few examples which will enable you to write a wide range of Cucumber steps. Below are some I found the most useful.

Exact match

I know it’s a no-brainer but will get you started.

@Given("I have a cucumber step")
public void i_have_a_cucumber_step() throws Throwable {
    System.out.println("Step definition exact match");
}

Use anchors

Remember to use anchors to mark the beginning (^) and end of the expression ($). The step definition above will match both steps below:

Given I have a cucumber step
Given I have a cucumber step and a salad

What we really want is to match the first one and get Cucumber to give us a stub implementation of the second one. In order to avoid unexpected matches we need to add anchors:

@Given("^I have a cucumber step$")

Capture integers and strings

@Given("^I have (\\d+) (.*) in my basket$")
public void i_have_in_my_basket(int number, String veg) throws Throwable {
    System.out.println(format("I have {0} {1} in my basket", number, veg));
}

Let’s have a look at the step definition. By using round brackets we mark part of the expression as a capture group so that Cucumber can map it to a method parameter. In our case have the following patterns:

  • \d+ matching at least one digit, d represents a digit, + is a quantifier and means one or more times; the expression is escaped with a backslash, because it also is the escape character in Java we need to escape it with another backslash and we end up with \\d+
  • .+ matching at least one character, . (dot) represents any character

Use non-capturing groups

It may be useful to have a bit of flexibility and add words in the step which are not matched. This is what non-capturing groups can be used for. There is a ?: operator (question mark and colon) and if it is present at the beginning of the group it will not be mapped to method parameters.

@Given("^I have a (?:tasty|nasty|rusty) cucumber step$")
public void i_have_a_X_cucumber_step() throws Throwable {
    System.out.println("Step definition with a non-capturing group");
}

This step definition will match three different steps to one step definition. Note that I used logical operator described below.

Scenario: Non-capturing group        # cucumber/regex.feature:9
  Given I have a tasty cucumber step # CucumberSteps.i_have_a_X_cucumber_step()
  Given I have a nasty cucumber step # CucumberSteps.i_have_a_X_cucumber_step()
  Given I have a rusty cucumber step # CucumberSteps.i_have_a_X_cucumber_step()

Singular and plural

Use ? qualifier to match words in both singular and plural. ? at the end of a word makes the last letter optional. We can also use the logical alternative operator | (pipe) to support correct grammar as well as irregular plurals which will make sentence read better.

@Given("^There (?:is|are) (\\d+) (?:cats?|ox|oxen) fed by (\\d+) (?:persons?|people)$")
public void animals_fed_by_people(int animals, int persons) throws Throwable {
    System.out.println(
            format("{0} animal(s) fed by {1} person(s)", animals, persons));
}
Given There is 1 cat fed by 1 person
Given There are 2 cats fed by 1 person
Given There are 2 cats fed by 2 persons
Given There are 2 cats fed by 3 people
Given There is 1 ox fed by 4 persons
Given There are 3 oxen fed by 5 people

Use Data Tables

You can use DataTable to manage larger amount of data. They are quite powerful but not the most intuitive as you either need to deal with a list of maps or a map of lists.

@Given ("^I have the following order$")
public void i_have_the_following_order (DataTable table) throws Throwable {
    for (Map<String, String> map : table.asMaps(String.class, String.class)) {
        String vegetable = map.get("vegetable");
        String amount = map.get("amount");
        String cost = map.get("cost");
        System.out.println(
                format("Order of {0} {1}s at the cost of {2}", 
                amount, vegetable, cost));
    }
}
Scenario: Data tables
  Given I have the following order
    | vegetable | amount | cost |
    | cucumber  |   4    |  10  |
    | carrot    |   5    |   6  |
    | potato    |   6    |   4  |

Map data tables to domain objects

Luckily there are easier ways to access your data than DataTable. For instance you can create a domain object and have Cucumber map your data in a table to a list of these.

@Given("^I have another order$")
public void i_have_another_order(List<OrderItem> list) throws Throwable {
    for (OrderItem orderItem : list) {
        String vegetable = orderItem.getVegetable ();
        int amount = orderItem.getAmount();
        int cost = orderItem.getCost ();
        System.out.println(
                format("Order of {0} {1}s at the cost of {2}", 
                amount, vegetable, cost));
    }
}

Our domain object – OrderItem

package com.czeczotka.bdd.domain;

public class OrderItem {

    private String vegetable;
    private int amount;
    private int cost;

    public String getVegetable () {
        return vegetable;
    }

    public void setVegetable (String vegetable) {
        this.vegetable = vegetable;
    }

    public int getAmount () {
        return amount;
    }

    public void setAmount (int amount) {
        this.amount = amount;
    }

    public int getCost () {
        return cost;
    }

    public void setCost (int cost) {
        this.cost = cost;
    }
}
Scenario: List of domain objects
  Given I have another order
    | vegetable | amount | cost |
    | cucumber  |   4    |  10  |
    | carrot    |   5    |   6  |
    | potato    |   6    |   4  |

 More on Java and regular expressions

If you want a bit more detail on how regular expressions work in Java  probably the best  place to start is the Java Tutorial and the detailed javadoc for the Pattern class.

The code

The code of this post is on github so follow the link below to browse it.

http://github.com/czeczotka/cucumber-jvm-regex

You can easily clone and play with it locally by simply following these steps.

$ git clone https://github.com/czeczotka/cucumber-jvm-regex.git
$ cd cucumber-jvm-regex
$ mvn test

I believe with the tools described here you have enough options to get started and create powerful step definitions. Last thing to note is that when you run the code above the System.out.println will appear before Cucumber output and this is because Cucumber displays its output after scenario execution when system outs have already written to the output stream.