Skip to content

Commit

Permalink
Fix @TestTransaction for self-intercepted invocation
Browse files Browse the repository at this point in the history
  • Loading branch information
famod committed Apr 10, 2021
1 parent ef1f94a commit 69069dd
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 5 deletions.
Expand Up @@ -7,6 +7,7 @@
import javax.inject.Inject;
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;
import javax.transaction.Status;
import javax.transaction.UserTransaction;

import io.quarkus.narayana.jta.runtime.test.TestTransactionCallback;
Expand All @@ -28,6 +29,14 @@ public class TestTransactionInterceptor {

@AroundInvoke
public Object intercept(InvocationContext context) throws Exception {
// do nothing in case there is already a transaction (e.g. self-intercepted non-private non-test method in test class)
// w/o this check userTransaction.begin() would fail because there is already a tx associated with the current thread
if (userTransaction.getStatus() != Status.STATUS_NO_TRANSACTION) {
return context.proceed();
}

// an exception from proceed() has to be captured to avoid shadowing it in finally() with a exception from rollback()
Exception caught = null;
try {
userTransaction.begin();
for (TestTransactionCallback i : CALLBACKS) {
Expand All @@ -38,9 +47,19 @@ public Object intercept(InvocationContext context) throws Exception {
i.preRollback();
}
return result;
} catch (Exception e) {
caught = e;
throw e;
} finally {
userTransaction.rollback();
if (caught == null) {
userTransaction.rollback();
} else {
try {
userTransaction.rollback();
} catch (Exception e) {
caught.addSuppressed(e);
}
}
}
}

}
@@ -0,0 +1,44 @@
package io.quarkus.it.panache;

import javax.transaction.Transactional;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.MethodOrderer.MethodName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;

import io.quarkus.test.TestTransaction;
import io.quarkus.test.junit.QuarkusTest;

/**
* Tests that @TestTransaction works as expected when only used for a single test method
*/
@QuarkusTest
@TestMethodOrder(MethodName.class)
public class TestTransactionOnSingleMethodTest {

@Test
@TestTransaction
public void test1() {
Assertions.assertEquals(0, Beer.find("name", "Lager").count());
Beer b = new Beer();
b.name = "Lager";
Beer.persist(b);
}

@Test
@Transactional
public void test2() {
Assertions.assertEquals(0, Beer.find("name", "Lager").count());
Beer b = new Beer();
b.name = "Lager";
Beer.persist(b);
}

@Test
@Transactional
public void test3() {
Assertions.assertEquals(1, Beer.find("name", "Lager").count());
Beer.deleteAll();
}
}
@@ -1,20 +1,22 @@
package io.quarkus.it.panache;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.MethodOrderer.MethodName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;

import io.quarkus.test.TestTransaction;
import io.quarkus.test.junit.QuarkusTest;

/**
* Tests that @TestTransaction works as expected
* Tests that @TestTransaction works as expected when used for the entire class
*/
@QuarkusTest
@TestTransaction
@TestMethodOrder(MethodName.class)
public class TestTransactionTest {

@Test
@TestTransaction
public void test1() {
Assertions.assertEquals(0, Beer.find("name", "Lager").count());
Beer b = new Beer();
Expand All @@ -23,11 +25,20 @@ public void test1() {
}

@Test
@TestTransaction
public void test2() {
Assertions.assertEquals(0, Beer.find("name", "Lager").count());
// interceptor must not choke on this self-intercepted non-test method invocation
intentionallyNonPriveHelperMethod();
Beer b = new Beer();
b.name = "Lager";
Beer.persist(b);
}

@Test
public void test3() {
Assertions.assertEquals(0, Beer.find("name", "Lager").count());
}

void intentionallyNonPriveHelperMethod() {
}
}

0 comments on commit 69069dd

Please sign in to comment.