Igor Konoplyanko
Igor Konoplyanko

Reputation: 9374

How to unit-test that spring @Transactional is present?

I wonder how can I make unittest to ensure that all my DAOs have propagation=MANDATORY. I have implemented just a unit test to call dao.getAll() without a transaction, and fail if there was no exception. But this is not kind of full test, I can't check it for all child methods.

That's what I have now:

String[] beanNamesForType = applicationContext.getBeanNamesForType(Dao.class);
for (String beanName : beanNamesForType) {
    Dao bean = (Dao) applicationContext.getBean(beanName);

    try {
        bean.getAll();
        fail();
    } catch (IllegalTransactionStateException ex) {
        //This is expected
    }
}

Are there possibility just to check that all DAO methods are proxified with needed transaction propagation? Maybe to use reflection?

Upvotes: 2

Views: 1436

Answers (2)

rodrigobartels
rodrigobartels

Reputation: 841

I usually do it using the following JUnit Test Case:

/**
 * Test if all the @Services bean are annotated with the @Transactional
 * annotation.
 */
@Test
public void testServicesTransactionalAnnotations(){
    String[] beansNames = applicationContext.getBeanDefinitionNames();
    StringBuilder sb = new StringBuilder();
    for(String beanName : beansNames){
        Service serviceAnnotation = applicationContext.findAnnotationOnBean(beanName, Service.class);
        if(serviceAnnotation != null && applicationContext.findAnnotationOnBean(beanName,
                Transactional.class) != null){
            Transactional transactional = applicationContext.findAnnotationOnBean(beanName,
                    Transactional.class);
            if(!transactional.propagation().equals(Propagation.MANDATORY)){
                sb.append("Missing @Transactional Annotation in bean:").append(beanName).append("\n");
            }
    }
    Assert.assertTrue(sb.toString(), StringUtils.isBlank(sb.toString()));
}

It checks that all the beans annotated with @Service are marked as Transactional too. I use the String Builder to be able to know which beans are missing the annotation.

Upvotes: 3

Angular University
Angular University

Reputation: 43117

This can be done with an assertion utility method that uses TransactionSynchronizationManager class.

Check methods like TransactionSynchronizationManager.getCurrentTransactionIsolationLevel and ´isActualTransactionActive´.

It´s possible to get the transaction resource from the thread bound resource map, see the code for JtaTransactionManager and OpenEntityManagerInViewListener classes in spring source code.

Upvotes: 2

Related Questions