Skip to content

Latest commit

 

History

History
112 lines (85 loc) · 4.06 KB

utilities.adoc

File metadata and controls

112 lines (85 loc) · 4.06 KB

Utilities

Testing Time with MutableClock

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.

Example

Class under Test
link:{sourcedir}/utilities/AgeFilter.java[role=include]
  1. Clock is injected via constructor

  2. Clock is used to get the current date

Test
link:{sourcedir}/utilities/MutableClockDocSpec.groovy[role=include]
  1. MutableClock created with a well known time

  2. Clock is injected via constructor

  3. age is less than 18 so the result is false

  4. the clock is advanced by one day

  5. age is equal to 18 so the result is true

There are many more ways to modify MutableClock just have a look at the JavaDocs, or the test code spock.util.time.MutableClockSpec.

Collection Conditions

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 to Set 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’s containsInAnyOrder under the hood).

Lenient Match

link:{sourcedir}/utilities/CollectionConditions.groovy[role=include]
link:{sourcedir}/utilities/CollectionConditions.groovy[role=include]

Strict Match

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.

Interact with the file system using FileSystemFixture

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.

Examples

Creating a directory tree
link:{sourcedir}/utilities/FileSystemFixtureSpec.groovy[role=include]
Tip
To get the nice Groovy methods for Path, you need to add a dependency on groovy-nio.

Capture Values for Assertions with old()

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.

Example

Using old() to capture the old value of x
link:{sourcedir}/utilities/OldMethodSpec.groovy[role=include]