If we write a specification for a specific class we can indicate that class with the
@Subject annotation. This annotation is only for informational purposes, but can help in making sure we understand which class we are writing the specifications for. The annotation can either be used at class level or field level. If we use the annotation at class level we must specify the class or classes under test as argument for the annotation. If we apply the annotation to a field, the type of the field is used as the class under test. The field can be part of the class definition, but we can also apply the
@Subject annotation to fields inside a feature method.
We can use data pipes to write data driven tests in Spock. A data pipe (
<<) is fed by a data provider. We can use
Collection objects as data provider, but also
String objects and any class that implements the
Iterable interface. We can write our own data provider class if we implement the
We can write data driven tests with Spock. We can specify for example a data table or data pipes in a
where: block. If we use a data pipe we can specify a data provider that will return the values that are used on each iteration. If our data provider returns multiple results for each row we can assign them immediatelly to multiple variables. We must use the syntax
[var1, var2, var3] < < providerImpl to assign values to the data variables
var3. We know from Groovy the multiple assignment syntax with parenthesis (
(var1, var2, var3)), but with Spock we use square brackets.
We can use the
@IgnoreRest annotation in our Spock specifications to not run the annotated specifications or features. With the
@IgnoreIf annotation we can specify a condition that needs to evaluate to
true to not run the feature or specification. The argument of the annotation is a closure. Inside the closure we can access three extra variables:
properties (Java system properties),
env (environment variables) and
Spock’s unroll feature is very powerful. The provider data variables can be used in the method description of our specification features with placeholders. For each iteration the placeholders are replaced with correct values. This way we get a nice output where we immediately can see the values that were used to run the code. Placeholders are denoted by a hash sign (
#) followed by the variable name. We can even invoke no-argument methods on the variable values or access properties. For example if we have a String value we could get the upper case value with
#variableName.toUpperCase(). If we want to use more complex expressions we must introduce a new data variable in the
where block. The value of the variable will be determined for each test invocation and we can use the result as a value in the method description.
Gr8Conf 2014 in Copenhagen has been great. Three days filled with very informative talks, learning the latest from the Groovy community and mostly meeting all the people involved with the Groovy community, both project leads, members and users. Continue reading
Spock has some great features to write specifications or tests that are short and compact. One of them is the
old() method. The
old() method can only be used in a
then: block. With this method we get the value a statement had before the
when: block is executed.
There is really no excuse to not write unit tests in Grails. The support for writing tests is excellent, also for testing code that has to deal with the locale set in a user’s request. For example we could have a controller or taglib that needs to access the locale. In a unit test we can invoke the
addPreferredLocale() method on the mocked request object and assign a locale. The code under test uses the custom locale we set via this method.
Albert van Veen wrote a blog post about Using ArgumentMatchers with Mockito. The idea is to let a mocked or stubbed service return a different value based on the argument passed into the service. This is inspired me to write the same sample with Spock.
Spock already has built-in mock and stub support, so first of all we don’t need an extra library to support mocking and stubbing. We can easily create a mock or stub with the
Stub() methods. We will see usage of both in the following examples.
Willem Cheizoo already wrote an blog post about How to test for an exception with JUnit and this inspired me to write the same sample with Spock.
In Spock we can use the
thrown() method to check for exceptions. We can use it in a
then: block of our test.