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)
}