Workshop for testing Java projects with Spock and Groovy.
In order to get Spock into our Maven project, we need to do the following in our pom.xml.
- Add Groovy as a (test) dependency (see pom.xml).
- Add Spock dependency (see pom.xml).
- Add CGLib and Objenesis in order to be able to Mock classes (see pom.xml).
- Make Maven aware of
/src/test/groovy
being a test source directory since Maven’s default is/src/test/java
(see pom.xml). - Add the GMavenPlus plugin, to compile your Groovy sources (see pom.xml).
- Make Maven Surefire plugin aware of files ending with
*Spec
are test class files since Surefire’s default is*Test
(see pom.xml).
Read the Spock Primer section of the Spock Framework Reference Documentation to learn about the basic Spock terminology, fixture and feature methods, blocks and expectations.
Note that in contrast to the Spock Primer, I prefer using given
instead of setup
for I like my test to be as close to natural language as possible and setup
does not sound very natural to me.
Also I don't like block comments to stay in the test after it has been implemented (as suggested in the Specifications as Documentation section) for I want the code to be self-explanatory.
Then try to do the following objectives:
- The method
isOfAge
method in User is not implemented properly yet. However there is a test in UserClassSpec which is annotated with@PendingFeature
. ChangeisOfAge
, in order to make the test's expectation be true. Once you did, remove the annotation.
Don't implement the method, just make the test's expectation true doing the very least necessary. - The feature methods uses
given
,when
andthen
. Try to make it shorter using anexpect
block. - Our current implementation of User allows to create users who were not born yet. Write a
@PendingFeature
that expects that"creating a user with a future birthday throws an IllegalArgumentException"
. - Adjust User to make the feature no longer pending and remove the annotation.
- Write another feature method that specifies that
"no exception in thrown if the birthday is in the past"
.
Read the Data Driven Testing section of the Spock Framework Reference Documentation to learn about where
blocks and their data table and pipe notations and the @Unroll
annotation.
Then try to do the following objectives:
- If you did the very least necessary in part 1, the implementation of
isOfAge
is not really how its name suggests because not only users are of age whose 18th birthday is today! Write another feature method to ensure that"isOfAge should return true if the user's birthday is more than 18 years ago"
. Use awhere
block to test several cases. - Add an
@Unroll
annotation to get more information about which cases have succeeded and which did not. - Add another data driven test to test negative cases.
- Review your features and try to make more test data driven.
Read the Interaction Based Testing section of the Spock Framework Reference Documentation to learn about Mocks, Stubs and Spies.
Then try to do the following objectives:
- We want to write a test for the UserService which ensures that
"registerUser persists the user data via UserRepository"
. Use a Mock for the UserRepository since we don't want to test it here (and there is no implantation 😉). Feel free to use a Mock for the User object as well. - We want to avoid registering users which are already registered. Write another feature method that ensures that
"registerUser does not persist user data if the user name was registered before"
. Make your test succeed, ensuring that all others still don't fail. Also we might want to throw an exception in that case. - ...
- Spock Framework Reference Documentation, especially the Extensions section and the Modules section not used in this workshop.
- Idiomatic Spock is a presentation by Rob Flechter about som tricks how to write Spock specifications in a better way.
- Groovy documentation