Problem:
How to AutoCleanup Spock test resources? It turns out that Spock Framework has a flexible mechanism just for that purpose. Let’s write some code to test it!
Solution:
The following simple Java class will serve as a mannequin for tests of Spock’s @AutoCleanup feature:
package com.farenda.spock; public class VeryCostlyObject { public VeryCostlyObject() { System.out.println("Instantiating very costly object..."); System.out.println("...5 minutes later ;-)"); System.out.println("Done!"); } public void close() { System.out.println("Close method called!"); } public void dispose() { System.out.println("Dispose method called!"); } public void exceptional() { System.out.println("Exceptional method called!"); throw new RuntimeException("Cannot close the resource."); } public void anotherExceptional() { System.out.println("Another exceptional method called!"); throw new RuntimeException("Cannot close the resource."); } }
As you can see the class has a couple of methods that all serve for releasing resources. In the test below we’re going to show how to call that methods in a different ways:
package com.farenda.spock import spock.lang.AutoCleanup import spock.lang.Specification class AutoCleanupTest extends Specification { @AutoCleanup def resource = new VeryCostlyObject() @AutoCleanup('dispose') def anotherResource = new VeryCostlyObject() @AutoCleanup('exceptional') def faultyResource = new VeryCostlyObject() @AutoCleanup(value = 'anotherExceptional', quiet = true) def quiteResource = new VeryCostlyObject() def 'should close the resource'() { println 'Executing test' expect: Math.abs(-3) == 3 } }
The @AutoCleanup annotation works as follows:
- by default it calls close() method,
- cleanup method name can be passed as the single parameter or value when more attributes are used,
- exceptions from executed method are reported by default, as can be seen at the end of the output below,
- use quiet = true to silent exceptions from the method,
- if more that one object is annotated with @AutoCleanup then closing is performed in reverse order of declaration,
- cleanup of @Shared objects is performed after all tests (just like cleanupSpec()).
Let’s see how the above test is executed:
Instantiating very costly object... ...5 minutes later ;-) Done! Instantiating very costly object... ...5 minutes later ;-) Done! Instantiating very costly object... ...5 minutes later ;-) Done! Instantiating very costly object... ...5 minutes later ;-) Done! Executing test Another exceptional method called! Exceptional method called! Dispose method called! Close method called! java.lang.RuntimeException: Cannot close the resource. at com.farenda.spock.VeryCostlyObject.exceptional(VeryCostlyObject.java:21) at org.spockframework.runtime.extension.builtin.AutoCleanupInterceptor.intercept(AutoCleanupInterceptor.java:58) at org.spockframework.runtime.extension.MethodInvocation.proceed(MethodInvocation.java:87) at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117) at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Nice and useful feature. :-)