Spock 2¶
There are no special extensions for Spock 2 (like it was for spock 1), instead I did an extra integration library, so you can use existing Junit 5 extensions with spock.
Note
You are not limited to guicey junit 5 extensions, you can use (almost) any junit 5 extensions. And you can use any other spock extensions together with junit extensions.
Setup¶
You will need the following dependencies (assuming BOM used for versions management):
testImplementation 'ru.vyarus:spock-junit5'
testImplementation 'org.spockframework:spock-core:2.3-groovy-4.0'
testImplementation 'io.dropwizard:dropwizard-testing'
testImplementation 'org.junit.jupiter:junit-jupiter-api'
Usage¶
See junit 5 extensions docs for usage details (it's all used the same).
Warning
Junit 5 extensions would not work with @Shared
spock fields! You can still use
such fields directly, but don't expect junit 5 extensions to be able to work with such fields (they can't "see" it).
Here is a simple example:
@TestDropwizardApp(App)
class MyTest extends Specification {
@Inject MyService service
def "Check something" (ClientSupport client) {
when: "calling rest endpoint"
def res = client.targetRest("foo/bar").request()
.buildGet().invoke().readEntity(String)
then: "result correct"
res == "something"
and: "service called"
service.isCalled()
}
}
Tip
Note that parameter injection will also work in test and fixture (setup/cleanup) methods
Overall, you get best of both worlds: same extensions as in junit 5 (and ability to use all other junit extensions) and spock expressiveness for writing tests.
Testing commands¶
Warning
Commands execution overrides System IO and so can't run in parallel with other tests!
Use @Isolated
on such tests to prevent parallel execution with other tests
Command execution is usually a short-lived action, so it is not possible to write an extension for it. Command could be tested only with generic utility:
def "Test command execution"() {
when: "executing command"
CommandResult result = TestSupport.buildCommandRunner(App)
.run("cmd", "-p", "param")
then: "success"
result.successful
}
Read more details in junit 5 guide
Note
The same utility could be used to test application startup fails
Special cases¶
Junit 5 doc describes system stubs library usage. It is completely valid for spock, I'll just show a few examples here on how to:
- Modify (and reset) environment variables
- Modify (and reset) system properties
- Validate system output (e.g. testing logs)
- Intercepting system exit
@ExtendWith(SystemStubsExtension)
class StartupErrorTest extends Specification {
@SystemStub
SystemExit exit
@SystemStub
SystemErr err
def "Check app crash"() {
when: "starting app"
exit.execute(() -> {
new App().run(['server'] as String[])
});
then: "error"
exit.exitCode == 1
err.text.contains("Error message text")
}
}
@ExtendWith(SystemStubsExtension)
class EnvironmentChangeTest extends Specification {
@SystemStub
EnvironmentVariables ENV
@SystemStub
SystemOut out
@SystemStub
SystemProperties propsReset
def "Check variables mapping"() {
setup:
ENV.set("VAR", "1")
System.setProperty("foo", "bar") // OR propsReset.set("foo", "bar") - both works the same
when:
// something requiring custom env or property values
then:
// validate system output (e.g. logs correctness)
out.text.contains("Some message assumed to be logged")
Note
Use test framework-agnostic utilities to run application with configuration or to run application without web part (for faster test).