Cleaner Tests with Spock

One obvious fact about tests that is often overlooked is: tests are code. This implies that the tests, as any kind of code, have to be read, understood and maintained. We’re smart, educated guys, familiar with all the craftsmanship practices of Clean Code, so we keep our tests clean. And yet, if you’re like me, you might be dissatisfied with the way some of your tests look. Not so long ago, I found my way to resolve this problem – the Spock framework.

Let’s Groove

Spock tests are written in Groovy – a concise JVM language with a lot of syntactic sugar. Groovy has quite a few features that make it a perfect fit for testing:

  • Quoted identifiers – after enclosing an identifier in quotes, it can contain illegal characters like spaces or keywords
  • Type inference – you can skip types when declaring variables, constants and so on –  def or static final is enough:
  • Collection literals – you can declare collections using a friendly syntax. No more Arrays.asList() and others alike:
  • And more! I could keep going with this, but we’re not here to praise Groovy 😉

Hello, Spock!

Test classes in Spock are called specifications and they have to extend Specification class. A single test is called a feature method and is divided into blocks following BDD given-when-then style. Code speaks louder than words, so take a look at the following example:

In the then block, you put expressions that evaluate to a boolean, each in a new line. For simple cases, like the one above, we can combine when and then into an expect block:

As you can see, the feature methods benefit from Groovy’s quoted identifiers. Another nice thing is that they don’t require any special annotations.

Block Descriptions

To further align with the BDD style, Spocks allows you to specify descriptions for each block, by simply putting a String after block’s declaration:

Data-Driven Tests

Spock really shines out when it comes to data-driven tests, also known as parameterized tests (in JUnit world). Instead of creating multiple similar tests, custom assertion methods or returning ugly arrays of Objects, you simply put your data on a table or a pipe:

Clean Mocking

Spock ships with built-in mocking support. Recording and verifying a mock look (arguably) cleaner than in frameworks like Mockito:

Great Failure Messages

When a test fails, it’s sometimes hard to say why exactly did it fail. With Spock, this is much less of a problem than in JUnit. Just take a look at those cool failure messages:

And for mocks:

There’s More!

I don’t mean to rewrite or compete with Spock’s documentation, so we’ll end up here. Read the docs or just play with the framework if you wish to learn more. I hope that at least some of you are now convinced that it’s a great tool to write great tests.

About the Author Grzegorz Ziemoński

King of Tidy Java, nerd that thinks about producing perfect software all the time and proud owner of 2 cats.

follow me on:
  • Oliver Weiler

    Minor nitpick: You only get type-inference when using def in combination with @CompileStatic. Otherwise def means dynamically typed.

  • All of these points on spot on, but it would be good to include some of Spock’s drawbacks as well. For example, I recently encountered a test written in Spock and using the Data Driven capabilities mentioned above that made several hundred calls to our database. The DBA’s got a little upset when the test opened 690 DB connections and took the dev database down. The strengths can turn into weaknesses if not used judiciously.