All posts by Jakub

Introducing running-conversions

https://github.com/czeczotka/running-conversions

As part of my preparations for a half-marathon and later the full marathon I was following a training plan which more often than not left me with a pen and paper calculating different paces and times for running activities. For example if you want to run a half-marathon under 2 hours what pace should you aim for? If you run it at 5:20 km/min what would be your finish time? If your plan tells you to run an interval of 600 metres in 2m34s what should be your pace?

After some training I also realised that running trackers have an accuracy which leaves a lot to be desired. They are good at measuring time but your location, distance and as a result pace is more of an approximation than actual measurement. It was a slight disappointment when I missed my first 10k’s finish time by 30s while being convinced I will be spot on with the result. My tracker simply measured 10.3k distance instead of 10k and so the pace was overestimated (i.e.: I thought I was running 4:55 while it was more like 5:05). That’s how I learned that the only reliable way of controlling your pace is following your time and checking it on the marker points. So how do you know your splits? For instance if you want to run the marathon in 3h30min what should be your 5k splits?

In order to answer these questions I could use some of the online calculators but I decided to have my own pet project and implement a Scala tool to solve these problems. That’s how running-conversions project was born. The basic idea that you create an activity which is either based on the distance and time or distance and pace and then you can query its properties. I described the installation and usage in the project and here are some examples of the calculation you can do:

// calculate the total time of the activity
input:  marathon at "5:41" time 
output: 3h59m48s
// calculate the pace
input:  k10 in "49m00s" pace 
output: 4:54
// get 1 kilometre splits for an activity
input:  k10 in "44m30s"  splits
output: Map(1.0 -> 4m27s, 2.0 -> 8m54s, 3.0 -> 13m21s, 4.0 -> 17m48s, 5.0 -> 22m15s, 6.0 -> 26m42s, 7.0 -> 31m09s, 8.0 -> 35m36s, 9.0 -> 40m03s, 10.0 -> 44m30s)
// calculate 5k splits to run the marathon in 3 hours 45 minutes
input:  marathon in "3h45m" splits k5
output: Map(5.0 -> 26m35s, 10.0 -> 53m10s, 15.0 -> 1h19m45s, 20.0 -> 1h46m20s, 25.0 -> 2h12m55s, 30.0 -> 2h39m30s, 35.0 -> 3h06m05s, 40.0 -> 3h32m40s)
// calculate 400m splits to run 2000m in 8 minutes
input:  metres2000 in "8m00s" splits metres400
output: Map(0.4 -> 1m36s, 0.8 -> 3m12s, 1.2 -> 4m48s, 1.6 -> 6m24s, 2.0 -> 8m00s)

https://github.com/czeczotka/running-conversions

With the interface via Scala REPL or by writing your own code it’s a bit rough on the edges but it has solved my problems so far. Let me know you thoughs. I am keen to learn if anybody is doing some work in this area!

Yay for pbcopy and pbpaste!

You know the feeling when you discover a trick of the trade that absolutely blows your mind and five minutes later you find out you are the last to the party and you should know it anyway? Well, that’s me with pbcopy and pbpaste, two OS X programs that make command-line copy and paste operations much easier and neater.

Let’s say you want to find all Ruby source files in a directory and copy the list to the clipboard (or pasteboard and OS X man page refers to it):

$ find . -name "*.rb" | pbcopy

Now if you want to see what’s in your clipboard you can use cat or less to display it:

$ pbpaste | less

Copy file contents to the clipboard:

$ pbcopy < cukes/features/support/hooks.rb

And from the clipboard to a file:

$ pbpaste > script.rb

I'm a keyboard aficionado and I really like to interact with computers without the need to move my hands off the keyboard to the mouse or trackpad, especially when all I need is to copy the output of the last command so any shortcuts or tricks are welcome. I think these two will be very handy in the future.

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