In a previous blog post we learned how to use DataVariable
and DataVariables
to test asynchronous code. Spock also provides PollingConditions
as a way to test asynchronous code. The PollingConditions
class has the methods eventually
and within
that accept a closure where we can write our assertions on the results of the asynchronous code execution. Spock will try to evaluate conditions in the closure until they are true. By default the eventually
method will retry for 1 second with a delay of 0.1 second between each retry. We can change this by setting the properties timeout
, delay
, initialDelay
and factor
of the PollingConditions
class. For example to define the maximum retry period of 5 seconds and change the delay between retries to 0.5 seconds we create the following instance: new PollingConditions(timeout: 5, initialDelay: 0.5)
.
Instead of changing the PollingConditions
properties for extending the timeout we can also use the method within
and specify the timeout in seconds as the first argument. If the conditions can be evaluated correctly before the timeout has expired then the feature method of our specification will also finish earlier. The timeout is only the maximum time we want our feature method to run.
Continue reading →
Testing asynchronous code needs some special treatment. With synchronous code we get results from invoking method directly and in our tests or specifications we can easily assert the value. But when we don’t know when the results will be available after calling a method we need to wait for the results. So in our specification we actually block until the results from asynchronous code are available. One of the options Spock provides us to block our testing code and wait for the code to be finished is using the classes DataVariable
and DataVariables
. When we create a variable of type DataVariable
we can set
and get
one value result. The get
method will block until the value is available and we can write assertions on the value as we now know it is available. The set
method is used to assign a value to the BlockingVariable
, for example we can do this in a callback when the asynchronous method support a callback parameter.
The BlockingVariable
can only hold one value, with the other class BlockingVariables
we can store multiple values. The class acts like a Map
where we create a key with a value for storing the results from asynchronous calls. Each call to get the value for a given key will block until the result is available and ready to assert.
Continue reading →
If we write specification where we need to use files and directories we can use the @TempDir
annotation on a File
or Path
instance variable. By using this annotation we make sure the file is created in the directory defined by the Java system property java.io.tmpdir
. We could overwrite the temporary root directory using Spock configuration if we want, but the default should be okay for most situations. The @TempDir
annotation can actually be used on any class that has a constructor with a File
or Path
argument. Since Spock 2.2 we can use the FileSystemFixture
class provided by Spock. With this class we have a nice DSL to create directory structures and files in a simple matter. We can use the Groovy extensions to File
and Path
to also immediately create contents for the files. If we want to use the extensions to Path
we must make sure we include org.apache.groovy:groovy-nio
as dependency to our test runtime classpath. The FileSystemFixture
class also has the method copyFromClasspath
that we can use to copy files and their content directory into our newly created directory structure.
Continue reading →
Since Spock 2.1 we have 2 new operators we can use for assertions to check collections: =~
and ==~
. We can use these operators with implementations of the Iterable
interface when we want to check that a given collection has the same elements as an expected collection and we don’t care about the order of the elements. Without the new operators we would have to cast our collections to a Set
first and than use the ==
operator.
Continue reading →
Testing classes that work with date calculations based on the current date and time (now) can be difficult. First of all we must make sure our class under test accepts a java.time.Clock
instance. This allows us to provide a specific Clock
instance in our tests where we can define for example a fixed value, so our tests don’t break when the actual date and time changes. But this can still not be enough for classes that will behave different based on the value returned for now. The Clock
instances in Java are immutable, so it is not possible to change the date or time for a Clock
instance.
In Spock 2.0 we can use the new MutableClock
class in our specifications to have a Clock
that can be used to go forward or backward in time on the same Clock
instance. We can create a MutableClock
and pass it to the class under test. We can test the class with the initial date and time of the Clock
object, then change the date and time for the clock and test the class again without having to create a new instance of the class under test. This is handy in situations like a queue implementation, where a message delivery date could be used to see if messages need to be delivered or not. By changing the date and time of the clock that is passed to the queue implementation we can write specifications that can check the functionality of the queue instance.
Continue reading →
In Spock we can also get a hold on the arguments that are passed to method call of a mock and we can write assertions to check the parameters for certain conditions.
When we create a mock in Spock and invoke a method on the mock the arguments are matched using the equals() implementation of the argument type. If they are not equal Spock will tell us by showing a message that there are too few invocations of the method call. Let’s show this with an example. First we create some classes we want to test:
Continue reading →
Creating and working with mocks and stubs in Spock is easy. If we want to interact with our mocks and stubs we have several options to return values. One of the options is the triple right shift operator >>>
. With this operator we can define different return values for multiple invocations of the stubbed or mocked method. For example we can use the >>>
operator followed by a list of return values ['abc', 'def', 'ghi']
. On the first invocation abc
is return, the second invocation returns def
and the third (and following) invocation(s) return ghi
.
In the following specification we have a class under test StringUtil
. The class has a dependency on an implementation of the Calculator
interface. We mock this interface in our specification. We expect the calculateSize
method is invoked 5 times, but we only provide 3 values for the invocations. This means the first time 1
is used, the second time 3
is used and the remaining invocations get the value 4
:
Continue reading →
In a previous blog post we have seen the IgnoreIf
extension. There is also a counterpart: the Requires
extension. If we apply this extension to a feature method or specification class than the method or whole class is executed when the condition for the @Requires
annotation is true. If the condition is false the method or specification is not executed. As a value for the @Requires
annotation we must specify a closure. In the closure Spock adds some properties we can use for our conditions:
jvm
can be used to check a Java version or compatibility.
sys
returns the Java system properties.
env
used to access environment variables.
os
can be used to check for operating system names.
javaVersion
has the Java version as BigDecimal
, eg. 1.8.
Continue reading →
If we need to add a Java system property or change the value of a Java system property inside our specification, then the change is kept as long as the JVM is running. We can make sure that changes to Java system properties are restored after a feature method has run. Spock offers the RestoreSystemProperties
extension that saves the current Java system properties before a method is run and restores the values after the method is finished. We use the extension with the @RestoreSystemProperties
annotation. The annotation can be applied at specification level or per feature method.
In the following example we see that changes to the Java system properties in the first method are undone again in the second method:
Continue reading →
Spcok has a lot of nice extensions we can use in our specifications. The AutoCleanup
extension makes sure the close()
method of an object is called each time a feature method is finished. We could invoke the close()
method also from the cleanup
method in our specification, but with the @AutoCleanup
annotation it is easier and immediately shows our intention. If the object we apply the annotation to doesn't have a close()
method to invoke we can specify the method name as the value for the annotation. Finally we can set the attribute quiet
to true
if we don't want to see any exceptions that are raised when the close()
method (or custom method name, that is specified) is invoked.
In the following example code we have a specification that is testing the WatchService
implementation. The implementation also implements the Closeable
interface, which means we can use the close()
method to cleanup the object properly. We also have a custom class WorkDir
with a delete()
method that needs to be invoked.
Continue reading →
Spock is able to change the execution order of test methods in a specification. We can tell Spock to re-run failing methods before successful methods. And if we have multiple failing or successful tests, than first run the fastest methods, followed by the slower methods. This way when we re-run the specification we immediately see the failing methods and could stop the execution and fix the errors. We must set the property optimizeRunOrder
in the runner
configuration of the Spock configuration file. A Spock configuration file with the name SpockConfig.groovy
can be placed in the classpath of our test execution or in our USER_HOME/.spock
directory. We can also use the Java system property spock.configuration
and assign the filename of our Spock configuration file.
In the following example we have a specification with different methods that can be successful or fail and have different durations when executed:
Continue reading →
One of the lesser known and documented features of Spock if the external Spock configuration file. In this file we can for example specify which specifications to include or exclude from a test run. We can specify a class name (for example a base specification class, like DatabaseSpec
) or an annotation. In this post we see how to use annotations to have some specifications run and others not.
The external Spock configuration file is actually a Groovy script file. We must specify a runner
method with a closure argument where we configure basically the test runner. To include specification classes or methods with a certain annotation applied to them we configure the include
property of the test runner. To exclude a class or method we use the exclude
property. Because the configuration file is a Groovy script we can use everything Groovy has to offer, like conditional statements, println
statements and more.
Continue reading →