I have to test a pessimistic lock implementation done with Micronaut data and Hibernate. When I am running the JUnit test case,with command gradle test
it is giving error
io.micronaut.context.exceptions.BeanInstantiationException: Error instantiating bean of type [org.hibernate.Session]: Could not obtain transaction-synchronized Session for current thread
But the function (orgAccountRepository.findTop1ByStatus) is working as expected, when called in the context of a controller.
To make things even weird, the test run successfully when executed with vs code java test runner.
This test is to verify that the pessimistic write lock on table rows are working. So essentially I have to create multiple concurrent transactions that compete to acquire lock and then verify that the locking mechanism is working.
Can someone give any advice on defining transactions with JUnit.
@Repository
public abstract class OrgAccountRepository implements CrudRepository<OrgAccount, String> {
private final EntityManager entityManager;
public OrgAccountRepository(EntityManager entityManager) {
this.entityManager = entityManager;
}
public Optional<OrgAccount> findTop1ByStatus(OrgAccountStatusName name) {
// Lock the result rows with PESSIMISTIC_WRITE lock
List<OrgAccount> orgAccounts = entityManager
.createQuery("FROM OrgAccount AS oa WHERE oa.status = :status", OrgAccount.class)
.setLockMode(LockModeType.PESSIMISTIC_WRITE).setParameter("status", name)
.getResultList();
if (orgAccounts.size() > 0) {
return Optional.ofNullable(orgAccounts.get(0));
}
return Optional.ofNullable(null);
}
}
@MicronautTest(environments = {"test"})
public class LockTableTest {
@Inject
LockTableHelper lockTableHelper;
@Test
void test() {
Thread t1 = new Thread() {
public void run() {
lockTableHelper.testRun();
}
};
t1.start();
//<Thread join and other logics>
....
....
}
}
}
public class LockTableHelper {
private final Logger log = LoggerFactory.getLogger(LockTableHelper.class);
@Inject
OrgAccountRepository orgAccountRepository;
@Transactional
public void testRun() {
Optional<OrgAccount> account =
orgAccountRepository.findTop1ByStatus(OrgAccountStatusName.UNASSIGNED);
}
}