5

Does spock has any Test event listener like how TestNg has ITestListener. ?

So that I can have access, when the test cases failed etc.

kazanaki
  • 7,988
  • 8
  • 52
  • 79
batman
  • 4,728
  • 8
  • 39
  • 45

2 Answers2

7

Spock does have listeners. Unfortunately the official documentation, which is otherwise excellent, has "TODO" under Writing Custom Extensions: http://spockframework.github.io/spock/docs/1.0/extensions.html.

Update: The official docs have been updated to include helpful information about custom extensions: http://spockframework.org/spock/docs/1.1/extensions.html. See those for more details.

There are two ways: Annotation-based and Global.

Annotation-based

Three pieces here: the annotation, the extension, and the listener.

The annotation:

    import java.lang.annotation.*
    import org.spockframework.runtime.extension.ExtensionAnnotation

    @Retention(RetentionPolicy.RUNTIME)
    @Target([ElementType.TYPE, ElementType.METHOD])
    @ExtensionAnnotation(ListenForErrorsExtension)
    @interface ListenForErrors {}

The extension (Updated):

    import org.spockframework.runtime.extension.AbstractAnnotationDrivenExtension
    import org.spockframework.runtime.model.SpecInfo

    class ListenForErrorsExtension extends AbstractAnnotationDrivenExtension<ListenForErrors> {
        void visitSpec(SpecInfo spec) {
            spec.addListener(new ListenForErrorsListener())
        }

       @Override
       void visitSpecAnnotation(ListenForErrors annotation, SpecInfo spec){
        println "do whatever you need here if you do. This method will throw an error unless you override it"
    }
    }

The listener:

    import org.spockframework.runtime.AbstractRunListener
    import org.spockframework.runtime.model.ErrorInfo

    class ListenForErrorsListener extends AbstractRunListener {
        void error(ErrorInfo error) {
            println "Test failed: ${error.method.name}"
            // Do other handling here
        }
    }

You can then use your new annotation on a Spec class or method:

    @ListenForErrors
    class MySpec extends Specification {
        ...
    }

Global

This also has three pieces: the extension, the listener, and the registration.

    class ListenForErrorsExtension implements IGlobalExtension {
        void visitSpec(SpecInfo specInfo) {
            specInfo.addListener(new ListenForErrorsListener())
        }
    }

You can use the same ListenForErrorsListener class as above.

To register the extension, create a file named org.spockframework.runtime.extension.IGlobalExtension in the META-INF/services directory. If using Gradle/Maven, this will be under src/test/resources. This file should contain only the fully qualified class name of your global extension, for example:

com.example.tests.ListenForErrorsExtension

References

For examples, see the Spock built-in extensions here: https://github.com/spockframework/spock/tree/groovy-1.8/spock-core/src/main/java/spock/lang https://github.com/spockframework/spock/tree/groovy-1.8/spock-core/src/main/java/org/spockframework/runtime/extension/builtin

sonique
  • 4,539
  • 2
  • 30
  • 39
thecodesmith_
  • 1,277
  • 8
  • 18
  • 1
    Hi, I do everything like described in "Annotation-based" section but when I execute my annotated specification I get such exception: "org.spockframework.runtime.InvalidSpecException: @ListenForErrors may not be applied to Specs". – MantasG Jan 23 '18 at 16:42
0

Spock has interaction listening via Mock:

def "should send messages to all subscribers"() {
    given:
    def subscriber = Mock(Subscriber)

    when:
    publisher.send("hello")

    then:
    1 * subscriber.receive("hello")
}

See the interaction based testing in the docs

Ross
  • 17,861
  • 2
  • 55
  • 73