When working with dates or time we often have the problem of writing stable tests.
Java only provides a FixedClock
for testing.
However, often time related code has to deal with the change of time,
so a fixed clock is not enough or makes the test harder to follow.
The prerequisite for using both FixedClock
and Spocks MutableClock
is that the production code,
actually uses a configurable Clock
and not just the parameterless Instant.now()
or the corresponding methods in the other java.time.*
classes.
link:{sourcedir}/utilities/AgeFilter.java[role=include]
-
Clock
is injected via constructor -
Clock
is used to get the current date
link:{sourcedir}/utilities/MutableClockDocSpec.groovy[role=include]
-
MutableClock
created with a well known time -
Clock
is injected via constructor -
age
is less than18
so the result isfalse
-
the clock is advanced by one day
-
age
is equal to18
so the result istrue
There are many more ways to modify MutableClock
just have a look at the JavaDocs, or the test code spock.util.time.MutableClockSpec
.
Sometimes, you want to assert the elements of a collection regardless of their order.
The Groovy way to do this is to cast both to Set
, i.e. x as Set == [1, 2, 3] as Set
.
While this works, it is very noisy.
Since Spock 2.1 you can use two new conditions:
-
x =~ [1, 2, 3]
is a lenient match, i.e., checking that x contains at least one instance of every item in the list (same semantics as casting both toSet
before comparing). -
x ==~ [1, 2, 3, 3]
is a strict match, i.e., checking that x contains exactly the items in the list regardless of their order (using Hamcrest’scontainsInAnyOrder
under the hood).
link:{sourcedir}/utilities/CollectionConditions.groovy[role=include]
link:{sourcedir}/utilities/CollectionConditions.groovy[role=include]
link:{sourcedir}/utilities/CollectionConditions.groovy[role=include]
link:{sourcedir}/utilities/CollectionConditions.groovy[role=include]
Note
|
Both operands must either be Iterable or an array for this to work.
Otherwise, it will be treated like the standard groovy find operator or match operators.
|
In integration tests you often have to prepare the file system for a test.
For trivial cases like creating a single temp directory, you can use the @TempDir extension directly.
However, for more complex cases like creating a directory tree FileSystemFixture
offers convenience and better readability.
It can be helpful to know the old value of an expression before the when:
was executed.
This allows you to compare the changes made by a when:
block.
You can capture the old value of an expression with old(<expr>)
in a then:
block,
which will return the value of the <expr>
before the previous when:
block is executed.
The usage of the old()
method makes a test less fragile, because you can assert the difference,
which was made by the when:
block.