Annotation Interface ExpectedToFail


Inverts the pass/fail outcome of the annotated test method (or every test method on the annotated class): a test that throws is reported as passing, and a test that completes normally is reported as failing.

Useful for asserting that some condition reliably fails, and for testing test-infrastructure code that should propagate failures.

Optionally constrain the expected failure by exception type or by a closure predicate evaluated against the thrown exception:

 @Test
 @ExpectedToFail(IllegalStateException)
 void mustThrowIse() { throw new IllegalStateException("boom") }

 @Test
 @ExpectedToFail({ ex instanceof RuntimeException && message.contains('boom') })
 void mustMatchPredicate() { throw new RuntimeException("kaboom!") }
 

Closure predicates are evaluated with three bindings: ex (the thrown exception), message (its message, possibly null), and cause (its cause, possibly null). The test is reported as passing iff the predicate returns a Groovy-truthy value.

For callers who want compile-time enforcement that the configured class is a Throwable subclass, set exception() instead of (or alongside) value(). exception and a closure value compose: the type acts as a guard that runs before the predicate, so the closure body can drop the ex instanceof X boilerplate. exception and a Throwable value are mutually exclusive (they would specify the type twice).

TestAbortedException (the exception thrown by JUnit Assumptions) is never treated as the expected failure; it's always rethrown so the test is reported as aborted.

Composition with ForkedJvm: works in either declaration order via explicit coordination between the two extensions (no reliance on annotation iteration order). When @ExpectedToFail is declared before @ForkedJvm (i.e., outer), the inversion happens in the parent JVM after the failure propagates from the fork — exercising @ForkedJvm's serialization. When declared after (inner), the inversion happens inside the forked child.

Since:
6.0.0
  • Optional Element Summary

    Optional Elements
    Modifier and Type
    Optional Element
    Description
    Class<? extends Throwable>
    Type-safe alternative to value(): declares the expected exception type with compile-time enforcement that it is a Throwable subclass.
    Optional human-readable explanation of why this test is expected to fail.
    Either an expected Throwable subclass or a Closure predicate evaluated against the thrown exception.
  • Element Details

    • value

      Class<?> value
      Either an expected Throwable subclass or a Closure predicate evaluated against the thrown exception. Defaults to Throwable, which matches anything.

      When set to a Throwable subclass, mutually exclusive with exception(). When set to a closure, composes with exception(): the type guard is checked first, then the closure predicate.

      Default:
      java.lang.Throwable.class
    • exception

      Class<? extends Throwable> exception
      Type-safe alternative to value(): declares the expected exception type with compile-time enforcement that it is a Throwable subclass. Defaults to Throwable, which matches anything.

      Mutually exclusive with a Throwable value(); composes with a closure value() as a type guard evaluated before the predicate.

      Default:
      java.lang.Throwable.class
    • reason

      String reason
      Optional human-readable explanation of why this test is expected to fail. Surfaced in the failure message when the test unexpectedly passes.
      Default:
      ""