Question

I try to create testcases for @Transactional.

@ContextConfiguration(locations = {"classpath:/META-INF/spring/app-context.xml" })
@RunWith(SpringJUnit4ClassRunner.class)
public class TransactionalAnnotationTest {
    public static final BigDecimal PROD_ID = new BigDecimal(1234);

    @PersistenceContext
    HibernateEntityManager em;


    @Test
    public final void testTransactionIsolation() {
        String original = em.find(ProductImpl.class, PROD_ID).getDescription();
        // original = "Foo"
        updateTx(original);
    }

    @Transactional
    public final void updateTx(String original) {
        ProductImpl product = em.find(ProductImpl.class, PROD_ID);
        product.setDescription("Bar");
        whatIsInDB(original);
    }

    private void whatIsInDB(String original) {
        String sameTxDescription = em.find(ProductImpl.class, PROD_ID).getDescription();
        assert !sameTxDescription.equals(original);
    }
}

It fail! Should the second em.find not return a Product with "Bar"?

Was it helpful?

Solution 2

Hm, i got it to work.

  1. To test Transactions: a simple em.flush() is all i need (thanks to @TaoufikMohdit for the idea). If there is no transaction, flush() throws a TransactionRequiredException!
  2. @Transactional is for Spring-Managed-Beans only. So i create a Service:

    @Service
    public class BasicTransactionalService {
      @PersistenceContext
      HibernateEntityManager em;
    
      @Transactional
      public void testFlushInTransactional() {
        em.flush();
      }
    
      @Deprecated
      public void testFlushOutsideTransactional() {
        em.flush();
      }
    
      @Transactional
      public void testFlushSubroutineTransactional() {
        testFlushOutsideTransactional();
      }
    }
    
  3. I changed the Tests to:

    @Autowired
    BasicTransactionalService bean;
    
    @Test
    public void testTransactionIsolation() {
      bean.testFlushInTransactional();
    }
    
    @Test(expected = TransactionRequiredException.class)
    @SuppressWarnings("deprecation")
    public void testThrowsTransactionRequiredException() {
      bean.testFlushOutsideTransactional();
    }
    
    @Test
    public void testTransactionalSubroutine(){
      bean.testFlushSubroutineTransactional();
    }
    

Now it works fine.

BTW This is my app-config.xml

<beans>
  <bean class="BasicTransactionalService" />
  <bean class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean" />
  <bean class="org.springframework.orm.jpa.JpaTransactionManager" />
  <tx:annotation-driven />
<beans>

OTHER TIPS

Try explicitly flushing the context after setting the "description" field

product.setDescription("Bar");
em.flush();
whatIsInDB(original);

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top