2

Spring documentation warns about False Positives in Transactional tests and suggest the following:

// ...

@Autowired
SessionFactory sessionFactory;

@Transactional
@Test // no expected exception!
public void falsePositive() {
    updateEntityInHibernateSession();
    // False positive: an exception will be thrown once the Hibernate
    // Session is finally flushed (i.e., in production code)
}

@Transactional
@Test(expected = ...)
public void updateWithSessionFlush() {
    updateEntityInHibernateSession();
    // Manual flush is required to avoid false positive in test
    sessionFactory.getCurrentSession().flush();
}

// ...

I have the following base class:

@SpringBootTest
@Transactional
@AutoConfigureMockMvc
public abstract class BaseSpringBootTest {

and a class that extends it where I want to apply this practice of injecting the sessionFactory:

public class EmployeeRepositoryTest extends BaseSpringBootTest {

  @Autowired
  SessionFactory sessionFactory

but I am getting:

NoSuchBeanDefinitionException: No qualifying bean of type 'org.hibernate.SessionFactory' available

I also tried injecting

@Autowired
EntityManagerFactory entityManagerFactory;

and then calling:

SessionFactory sessionFactory = entityManagerFactory.unwrap(SessionFactory.class);
sessionFactory.getCurrentSession();

but this throws the following Exception:

org.hibernate.HibernateException: No CurrentSessionContext configured!

How do I get a reference to currentSession in a test, so that I can finally call:

sessionFactory.getCurrentSession().flush();

as documented in Spring Boot documentation?

luiscla27
  • 4,956
  • 37
  • 49
Koray Tugay
  • 22,894
  • 45
  • 188
  • 319
  • That isn't the Spring Boot documentation that is the Spring documentation. Which is a different thing!. Just inject the `EntityManager` as Spring Boot by default uses JPA. – M. Deinum Sep 14 '20 at 05:19
  • 1
    @M.Deinum Thank you, fixed the question. I was just tired I guess. The problem with injecting `EntityManager` is, the thrown exception is not `DataIntegrityViolationException` but rather `PersistenceException`. I guess it is ok, it is the closest I can get to real behaviour.. – Koray Tugay Sep 14 '20 at 23:48
  • 1
    You won't get a `DataIntegrityViolationException` with a `Session` either as direct use of the persistence implementation bypasses the Spring exception handling for data access technologies. – M. Deinum Sep 15 '20 at 05:06
  • Did you try `TransactionAspectSupport.currentTransactionStatus().flush();`? – Antoniossss May 10 '23 at 14:04
  • Are you aware of this post? https://stackoverflow.com/questions/1500775/proper-way-to-autowire-a-hibernate-session-in-a-spring-transaction-junit-test it seems to be a solution. – Tr1monster May 10 '23 at 14:46
  • @Tr1monster these answers are from 2009 so i'm not sure they're really valid anymore – bharal May 10 '23 at 20:10
  • @bharal, have you tried to also add `@RunWith(SpringRunner.class)` to your `BaseSpringBootTest` class?? – luiscla27 May 16 '23 at 23:52
  • Also, @bharal. please try moving all your annotations from your abstract class to `EmployeeRepositoryTest`. idk what java version you're using... but Java inherit annotations only since v9+, your issue might be related to that... – luiscla27 May 16 '23 at 23:56

1 Answers1

1

You just need to read on/little scroll:

The following example shows matching methods for JPA:

@PersistenceContext EntityManager entityManager;

@Transactional
@Test // no expected exception!
public void falsePositive() {
    updateEntityInJpaPersistenceContext();
    // False positive: an exception will be thrown once the JPA
    // EntityManager is finally flushed (i.e., in production code)
}

@Transactional
@Test(expected = ...)
public void updateWithEntityManagerFlush() {
    updateEntityInJpaPersistenceContext();
    // Manual flush is required to avoid false positive in test
    entityManager.flush();
}

This should solve (all) your:

org.hibernate.HibernateException: No CurrentSessionContext configured!

..problems.

xerx593
  • 12,237
  • 5
  • 33
  • 64
  • im curious how to get the current session, or failing that to avoid the hibernate exception. sorry, but i don't quite understand the answer you've posted - it is some code but i don't quite see what the solution is, and you seem to be quoting something, but i'm not sure what? – bharal May 10 '23 at 20:09
  • I am quoting your link ... the solution (i think) is: to stick to "jpa" classes (not "hibernate") – xerx593 May 10 '23 at 20:19
  • and `entityManager.flush();` is equivalent for (the desired) `sessionFactory.getCurrentSession().flush();` – xerx593 May 10 '23 at 20:22
  • oh i didn't ask the question so i don't know what link you refer to - but i take it it is the "spring documentation" mentioned at the beginning? – bharal May 10 '23 at 20:26
  • sry, my bad... correct [this link](https://docs.spring.io/spring/docs/current/spring-framework-reference/testing.html#testcontext-tx-annotation-demo) ..little scrolling/ctrl+f and m.d.'s comment "Just inject the EntityManager as *Spring Boot by default uses JPA.*" – xerx593 May 10 '23 at 20:28