Monday, May 14, 2012

Spock: Using @Unroll with Parameterized Data

With Spock, a testing framework for Java and Groovy, we can easily write tests using parameterized data. One feature I'd like to share is the @Unroll annotation which makes working with parameterized data easier as each entry in the table will be treated as separate test.

Take this example that tests the addition of two numbers:

    package org.stash.example

    import spock.lang.Specification
    import spock.lang.Unroll

    class AdderSpec extends Specification {

        Adder adder = new Adder()

        @Unroll("#i + #j == #sum?")
        def 'can add two numbers together to produce a sum'() {
            expect:
                sum == adder.add(i, j)
            where:
                i | j | sum
                1 | 2 | 3
                2 | 2 | 4
               -1 | 2 | 0
        }
    }

Prior to adding the @Unroll annotation, our test output in Maven would look like this:

    Running org.stash.example.AdderSpec
    Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.374 sec

The three separate test are treated as a whole. With the annotation added:

    Running org.stash.example.AdderSpec
    Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.388 sec

Now each entry for the data table is treated as a separate test

If we were to force a failure, by say expecting -1 + 2 == 0...

    Running org.stash.example.AdderSpec
    Tests run: 3, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.501 sec <<< FAILURE!

    Results :

    Failed tests:   -1 + 2 == 0?(org.stash.example.AdderSpec): Condition not satisfied:(..)

We now see in the output the message attached to the annotation with the values used in the test from the data table filtered in!

Hessian: Expected "End of Map" Exception

We've been working with Hessian services lately to send Java objects over the wire. So far the work has been trouble free, but from time to time, we run into some cryptic error messages. I'll document one here in case someone runs into a same problem.

Take the following error:

  Caused by: com.caucho.hessian.io.HessianProtocolException: expected end of map ('Z') at 'end of file'

This appear simply means, at least in our case, that the object being received by the caller of a Hessian service cannot be deserialized, either the object being transferred directly, or object contained with the transferred object's graph.

To resolve make sure every object in the graph implements java.io.Serializable.

Note: The above error came from com.caucho:hessian:jar:4.0.7.