{"record":{"id":"ec6ae739d6a60f12","repo":"quarkusio/quarkus","slug":"a-test-method-annotated-with-testreactivetransact","errorCode":null,"errorMessage":"A test method annotated with @TestReactiveTransaction must accept io.quarkus.test.vertx.UniAsserter","messagePattern":"A test method annotated with @TestReactiveTransaction must accept io\\.quarkus\\.test\\.vertx\\.UniAsserter","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"extensions/panache/hibernate-reactive-panache-common/runtime/src/main/java/io/quarkus/hibernate/reactive/panache/common/runtime/TestReactiveTransactionalInterceptor.java","lineNumber":26,"sourceCode":"import jakarta.interceptor.AroundInvoke;\nimport jakarta.interceptor.InvocationContext;\n\nimport io.smallrye.mutiny.Uni;\n\npublic class TestReactiveTransactionalInterceptor {\n\n    private static final String JUNIT_TEST_ANN = \"org.junit.jupiter.api.Test\";\n    private static final String JUNIT_BEFORE_EACH_ANN = \"org.junit.jupiter.api.BeforeEach\";\n    private static final String JUNIT_AFTER_EACH_ANN = \"org.junit.jupiter.api.AfterEach\";\n    private static final String UNI_ASSERTER_CLASS = \"io.quarkus.test.vertx.UniAsserter\";\n\n    @AroundInvoke\n    public Object intercept(InvocationContext context) throws Exception {\n        if (isSpecialTestMethod(context)) {\n            return handleSpecialTestMethod(context);\n        }\n        // TODO validate this requirement during build\n        throw new IllegalStateException(\n                \"A test method annotated with @TestReactiveTransaction must accept io.quarkus.test.vertx.UniAsserter\");\n    }\n\n    protected boolean isSpecialTestMethod(InvocationContext ic) {\n        Method method = ic.getMethod();\n        return hasParameter(UNI_ASSERTER_CLASS, method)\n                && (hasAnnotation(JUNIT_TEST_ANN, method)\n                        || hasAnnotation(JUNIT_BEFORE_EACH_ANN, method)\n                        || hasAnnotation(JUNIT_AFTER_EACH_ANN, method));\n    }\n\n    protected Object handleSpecialTestMethod(InvocationContext ic) {\n        // let's not deal with generics/erasure\n        Class<?>[] parameterTypes = ic.getMethod().getParameterTypes();\n        Object uniAsserter = null;\n        Class<?> uniAsserterClass = null;\n        for (int i = 0; i < parameterTypes.length; i++) {\n            Class<?> klass = parameterTypes[i];","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/panache/hibernate-reactive-panache-common/runtime/src/main/java/io/quarkus/hibernate/reactive/panache/common/runtime/TestReactiveTransactionalInterceptor.java#L8-L44","documentation":"Methods annotated with @TestReactiveTransaction run under a reactive transaction and must use the UniAsserter callback style of Quarkus reactive testing; the interceptor detects whether the method has a UniAsserter parameter. If it does not, there is no way to drive the reactive chain, so the interceptor throws immediately at call time.","triggerScenarios":"A test method annotated with @TestReactiveTransaction is invoked by the interceptor and its Method has no io.quarkus.test.vertx.UniAsserter parameter (isSpecialTestMethod returns false).","commonSituations":"Writing a plain void/synchronous test method and annotating it with @TestReactiveTransaction expecting declarative transaction semantics; copy-pasting @Transactional test style into a reactive test; renaming/refactoring that removed the UniAsserter parameter.","solutions":["Add an io.quarkus.test.vertx.UniAsserter parameter to the test method and use asserter.assertThat/Uni assertions","Remove @TestReactiveTransaction if the test does not need a reactive transaction","Use plain @TestReactiveTransaction with UniAsserter, or switch to inject + manually chaining Uni for non-test code"],"exampleFix":"// before\n@TestReactiveTransaction\nvoid testSave() {\n    entity.persist();\n}\n// after\n@TestReactiveTransaction\nvoid testSave(UniAsserter asserter) {\n    asserter.assertThat(() -> entity.persist().chain(() -> entity.count()), count -> count == 1);\n}","handlingStrategy":"validation","validationCode":"if (!java.util.Arrays.stream(testMethod.getParameterTypes()).anyMatch(p -> p == io.quarkus.test.vertx.UniAsserter.class)) {\n    throw new AssertionError(\"@TestReactiveTransaction test must accept UniAsserter\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always add UniAsserter parameter when using @TestReactiveTransaction","Let the IDE template generate reactive transactional tests","Review test signatures during code review"],"tags":["quarkus","panache","hibernate-reactive","testing"],"backgroundTag":"reactive-test-method-signature","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}