Home > Enterprise >  Exception handler for unexpected expceptions in Spock
Exception handler for unexpected expceptions in Spock

Time:08-14

Is there a way to handle unexpected exceptions in Spock? My use-case is to make test failures where exceptions are thrown better human-readable. E.g. when a test fails with an HttpClientErrorException, I would like to have the status code and the body in the printed test output.

e.g.

when:
restTemplate.getForObject(url, String)

then:
noExceptionThrown()

Now the getForObject() call throws an HttpClientErrorException I want an output like this:

Expected no exception to be thrown, but got 'HttpClientErrorException'
  Status-Code: 400
  Body: '{"error": "parameter foo missing"}'

CodePudding user response:

You can write a custom extension to handle these exceptions yourself, you can't use noExceptionThrown() in this case, as this would prevent the exception to leave the feature method.

import spock.lang.*;
import java.lang.annotation.*;
import org.spockframework.runtime.extension.*;
import org.spockframework.runtime.model.*;

class NiceExceptionsInterceptor implements IMethodInterceptor {
    static final NiceExceptionsInterceptor INSTANCE = new NiceExceptionsInterceptor()
    
    void intercept(IMethodInvocation invocation) throws Throwable {
        try {
            invocation.proceed()
        } catch (SpecialException e) {
            throw new AssertionError("Special Exception happened: " e.message)
        }
    }
}    

@Retention(RetentionPolicy.RUNTIME)
@Target([ElementType.TYPE, ElementType.METHOD])  
@ExtensionAnnotation(NiceExceptionsExtensions)
@interface NiceExceptions {

}

class NiceExceptionsExtensions implements IAnnotationDrivenExtension<NiceExceptions> {
    @Override
    void visitSpecAnnotation(NiceExceptions annotation, SpecInfo spec) {
        spec.bottomSpec.allFeatures.featureMethod*.addInterceptor(NiceExceptionsInterceptor.INSTANCE)
    }

    @Override
    void visitFeatureAnnotation(NiceExceptions annotation, FeatureInfo feature) {
        feature.featureMethod.addInterceptor(NiceExceptionsInterceptor.INSTANCE)
    }
}

// ---- Usage DEMO 

class SpecialException extends Exception {
    SpecialException(String message) {
        super(message)
    }
}

@NiceExceptions
class ASpec extends Specification {

    def "spec level"() {
        when:
            throw new SpecialException("Foo")
        then:
            true
    }
}



class BSpec extends Specification {

    @NiceExceptions
    def "test level"() {
        when:
            throw new SpecialException("Foo")
        then:
            true
    }

}

Try it in the Groovy Web Console

You can write you handler logic and extract any information in the catch-block.

        catch (SpecialException e) {
            throw new AssertionError("Special Exception happened: " e.message)
        }
  • Related