@Transactional ignored in any @Nested test class
See original GitHub issueDescribe the bug
According to the docs, @QuarkusTest
classes support the use of @Transactional
tests. ~This does not seem to be the case for test setup methods annotated with @BeforeEach
, though.~ Edit: This does not seem to be the case for @Nested
tests, though. (I have commented out irrelevant parts)
When running the following test, I get an exception telling me that user.delete()
has been called outside of a transaction:
@QuarkusTest
public class MyTest {
@Nested
@FlywayTest(value = @DataSource(url = "jdbc:h2:mem:test"))
public class NestedClass {
@Test
@Transactional
public void test() {
User user = User.findById("user1");
user.delete();
}
}
/* Edit: This was my original test case. turns out the aforementioned is sufficient
@Nested
@FlywayTest(value = @DataSource(url = "jdbc:h2:mem:test"), clean = false)
@DisplayName("when removing a user")
public class AfterRemovingUser {
@BeforeEach
@Transactional
public void setup() {
User user = User.findById("user1");
user.delete();
}
@Test
@Transactional
@DisplayName("the user's devices get deleted")
public void testCascadeToDevices() {
boolean match = Device.<Device>findAll().stream().anyMatch(d -> "user1".equals(d.owner.id));
Assertions.assertFalse(match);
}
}
*/
/* other tests */
}
javax.persistence.TransactionRequiredException: Transaction is not active, consider adding @Transactional to your method to automatically activate one.
at io.quarkus.hibernate.orm.runtime.session.TransactionScopedSession.remove(TransactionScopedSession.java:160)
at io.quarkus.hibernate.orm.runtime.session.ForwardingSession.remove(ForwardingSession.java:63)
at org.hibernate.Session_5b93bee577ae2f8d76647de04cfab36afbf52958_Synthetic_ClientProxy.remove(Session_5b93bee577ae2f8d76647de04cfab36afbf52958_Synthetic_ClientProxy.zig:1276)
at io.quarkus.hibernate.orm.panache.common.runtime.AbstractJpaOperations.delete(AbstractJpaOperations.java:122)
at io.quarkus.hibernate.orm.panache.PanacheEntityBase.delete(PanacheEntityBase.java:80)
at com.example.MyTest$AfterRemovingUser.setup(MyTest.java:50)
Expected behavior
Any method inside of a @QuarkusTest
supports @Transactional
in the same way.
Actual behavior
While @Transactional
~is supported on the @Test
methods themselves, it seems to be ignored during test setup.~ is supported on the root level, it is ignored in @Nested
tests.
How to Reproduce?
Create Panache entities for the following two tables and run the aforementioned test.
-- flyway ddl:
CREATE TABLE user
(
id VARCHAR(255) NOT NULL,
name VARCHAR(255) NOT NULL,
CONSTRAINT PK_USER PRIMARY KEY (id)
);
/*
-- CREATE TABLE device
(
id VARCHAR(255) NOT NULL,
user_id VARCHAR(255) NOT NULL,
name VARCHAR(255) NOT NULL,
CONSTRAINT PK_DEVICE PRIMARY KEY (id),
CONSTRAINT FK_DEVICE_ON_USER FOREIGN KEY (user_id) REFERENCES user (id) ON DELETE CASCADE
);
*/
-- flyway test data:
INSERT INTO user (id, name)
VALUES
('user1', 'User Name 1');
/*
INSERT INTO device (id, user_id, name)
VALUES
('device1', 'user1', 'Device 1'),
('device2', 'user1', 'Device 2');
*/
@Entity
@Table(name = "user")
public class User extends PanacheEntityBase {
@Id
@Column(name = "id", nullable = false)
public String id;
@OneToMany(mappedBy = "owner")
public Set<Device> devices = new HashSet<>();
@Column(name = "name", nullable = false)
public String name;
/* hashcode/equals/etc */
}
/*
@Entity
@Table(name = "device")
public class Device extends PanacheEntityBase {
@Id
@Column(name = "id", nullable = false)
public String id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", updatable = false, nullable = false)
public User owner;
@Column(name = "name", nullable = false)
public String name;
/ * hashcode/equals/etc */
*/
}
Output of uname -a
or ver
Darwin Kernel Version 20.6.0
Output of java -version
OpenJDK Runtime Environment Temurin-17+35 (build 17+35)
GraalVM version (if different from Java)
N/A
Quarkus version or git rev
2.5.0.Final
Build tool (ie. output of mvnw --version
or gradlew --version
)
Maven 3.8.3
Additional information
No response
Issue Analytics
- State:
- Created 2 years ago
- Comments:10 (6 by maintainers)
I can confirm this works in nested tests. For now this should be a feasible workaround.
Yeah, but the root cause it likely the same - JUnit does not allow us to control the lifecycle of the nested test