Announcement Announcement Module
Collapse
No announcement yet.
How to test @Transactional of my service class ? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • How to test @Transactional of my service class ?

    Hi all, I want to test the transactionality of my service. Following is my configuration file:
    HTML Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans 	xmlns="http://www.springframework.org/schema/beans" 
           	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           	xmlns:p="http://www.springframework.org/schema/p" 
           	xmlns:tx="http://www.springframework.org/schema/tx"
           	xmlns:context="http://www.springframework.org/schema/context"
           	xsi:schemaLocation="
    			http://www.springframework.org/schema/beans 
    			http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    			http://www.springframework.org/schema/tx 
    			http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
    			http://www.springframework.org/schema/context
    			http://www.springframework.org/schema/context/spring-context-3.0.xsd
    	   		">
    
    	<context:property-placeholder location="/WEB-INF/spring/hibernate-config/spring.properties" />
        
        <!-- Enable annotation style of managing transactions -->
    	<tx:annotation-driven transaction-manager="transactionManager" />	
       
        <!-- Declare the Hibernate SessionFactory for retrieving Hibernate sessions -->
        <!-- See http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/orm/hibernate3/annotation/AnnotationSessionFactoryBean.html --> 							
    	<!-- See http://docs.jboss.org/hibernate/stable/core/api/index.html?org/hibernate/SessionFactory.html -->
    	<!-- See http://docs.jboss.org/hibernate/stable/core/api/index.html?org/hibernate/Session.html -->
    	<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"
    				 p:dataSource-ref="dataSource"
    				 p:configLocation="${hibernate.config}"
    				 p:packagesToScan="it.obiectivo.ecoss"/>
    	
    	<!-- Declare a datasource that has pooling capabilities-->	 
    	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
    				destroy-method="close"
    				p:driverClass="${app.jdbc.driverClassName}"
    				p:jdbcUrl="${app.jdbc.url}"
    				p:user="${app.jdbc.username}"
    				p:password="${app.jdbc.password}"
    				p:acquireIncrement="5"
    				p:idleConnectionTestPeriod="60"
    				p:maxPoolSize="100"
    				p:maxStatements="50"
    				p:minPoolSize="10" />
    
    	<!-- Declare a transaction manager-->
    	<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager" 
           			p:sessionFactory-ref="sessionFactory" />
    
    </beans>
    my serice is:
    HTML Code:
    @Service("accessService")
    @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
    public class AccessService {
    protected static Logger logger = Logger.getLogger("gestoreService");
    	
    	@Autowired
        private GestoreDAO gestoreDAO;
    	
    	@Autowired
        private UtenteDAO utenteDAO;
    	
    	@Autowired
        private DistributoreDAO distributoreDAO;
    	
    	@Autowired
        private CredenzialiutenteDAO credenzialiutenteDAO;
    	
    	@Autowired
    	private SessionFactory sessionFactory;
    	
    	
    	/* ------------------------------------------ *
    	 * METODI PER L'Aggiunta DEGLI Accessi    *
    	 * ------------------------------------------ */
    	
    	
    	//Aggiungo un nuovo Accesso (Gestore + Credenzialiutente)
    	/*PARAMETRI DI INPUT: Entity, String, String*/
    	
    	/**
    	 * @todo
    	 * Il metodo attualmente è reso ATOMICO attraverso l'uso di istruzioni 
    	 * esplicite come: begin(), commit() e rollback(). Lo stesso dovrebbe 
    	 * integrare le stesse funzionalità in automatico grazie all'utilizzo
    	 * dell'annotazione: @Transactional o delle sue varianti 
    	 * es. @Transactional( propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, readOnly = true)
    	 */
    	public Boolean add(Gestore gestore, Credenzialiutente credenziali) throws Exception {
    		logger.debug("MakeAccessService: - creazione di un nuovo accesso x Gestore");
    		
    		Date dataInserimento = new Date();
    		gestore.setGestDataCreazione(dataInserimento);
    		
    		credenziali.setGestore(gestore);
    		credenziali.setDataInserimento(dataInserimento);
    		credenzialiutenteDAO.add(credenziali);
    		return true;
    	}
    	
    	//Aggiungo un nuovo Accesso (Distributore + Credenzialiutente)
    	public Boolean add(Distributore distributore, Credenzialiutente credenziali) {
    		logger.debug("MakeAccessService: - creazione di un nuovo accesso x Distributore");
    		
    		Gestore gestore = gestoreDAO.getByRagSociale(distributore.getGestore().getGestRagSociale());
    		distributore.setGestore(gestore);
    		
    		
    		Date dataInserimento = new Date();
    		distributore.setDistDataCreazione(dataInserimento);
    		
    		credenziali.setDistributore(distributore);
    		credenziali.setDataInserimento(dataInserimento);
    		credenzialiutenteDAO.add(credenziali);
    		return true;
    	}
    	
    	/** @todo
    	 * Dovrei trovare un sistema per poter ritornare, in caso di errore, il valore booleano. 
    	 * In particolare almeno per adesso, dalle ricerche effettuate, sembrerebbe che per poter
    	 * far funzionare correttamente il meccanismo delle transizioni, non si può usare il
    	 * try\catch statemen.
    	 * **/
    	//Aggiungo un nuovo Accesso (Utente + Credenzialiutente)
    	public Boolean add(Utente utente, Credenzialiutente credenziali) {
    		logger.debug("MakeAccessService: - creazione di un nuovo accesso x Utente");
    		
    		Gestore gestore = gestoreDAO.getByRagSociale(utente.getGestore().getGestRagSociale());
    		utente.setGestore(gestore);
    		String distRagSociale = utente.getDistributore().getDistRagSociale();
    		if(!distRagSociale.equals(null)){
    			Distributore distributore = distributoreDAO.getByRagSociale(utente.getDistributore().getDistRagSociale());
    			utente.setDistributore(distributore);
    		}
    		Date dataInserimento = new Date();
    		utente.setUteDataCreazione(dataInserimento);
    		credenziali.setUtente(utente);
    		credenziali.setDataInserimento(dataInserimento);
    		credenzialiutenteDAO.add(credenziali);
    		return true;
    	}
    	
    	/* ------------------------------------------ *
    	 * METODI PER L'Eliminazione DEGLI Accessi    *
    	 * ------------------------------------------ */
    	
    	//Elimina un accesso x Gestore
    	public Boolean delete(Gestore gestore) {
    		logger.debug("MakeAccessService: - eliminazione di un accesso x Gestore");
    		gestoreDAO.delete(gestore.getIdGestore());
    		return true;
    	}
    	
    	//Elimina un accesso x Distributore
    	public Boolean delete(Distributore distributore) {
    		logger.debug("MakeAccessService: - eliminazione di un accesso x Distributore");
    		distributoreDAO.delete(distributore.getIdDistributore());
    		return true;
    	}
    	
    	// Elimina un accesso x Utente
    	public Boolean delete(Utente utente) {
    		logger.debug("MakeAccessService: - eliminazione di un accesso x Utente");
    		utenteDAO.delete(utente.getIdUtente());
    		return true;
    	}
    }

  • #2
    If you are trying to test the transactional part (integartion testing)

    I would recommend you to go thru this spring documentaion
    http://static.springsource.org/sprin...tml#testing-tx

    Below sample code requires Junit 4 and spring test jars

    Code:
    @ContextConfiguration(locations={"classpath:yourcontextfile"})
    @RunWith(SpringJUnit4ClassRunner.class)
    @Transactional
    public class AccessServiceTest
    {
        @Autowired
        private AccessService service;
    
         @Test
          @Rollback(false) -- Default behavior transaction is rolled back (you can omit this tag)
          @Rollback(true) -- this will commit the transaction
         public void add()
         {
                //your code
          }
        
    
    
    }

    Comment


    • #3
      thanks you, but how I can generate an approprriate exception ???

      Comment


      • #4
        I think there is no other choice that extend your DAO and add some code to throw exception in the case you want
        eg:
        Code:
        class TestGestoreDAO extends GestoreDAO{
        ...
           public void delete(int id){
             super.delete(id);
             if (id==1) throw new NullPointerException();
           }
        ...
        }

        Comment


        • #5
          If I am reading your code correctly (I only understand parts of it), The only exceptions I see that could be generated are the data base related exceptions

          if they are data base related exceptions

          I would say let PersistenceExceptionTranslationPostProcessor translate them for you, I think over the years I learned that making db exceptions checked is not that use ful, because you cannot recover from them and also you can avoid all the glue code (try catch) required to use this Service.

          I do not want to make this a discussion on merits of checked vs run time exceptions(It is just a suggestion). If you have design reasons to use them please do so

          As for creating data base exceptions, I am sure you should be able to create a bad data set to generate them (some thing as simple as like null value on a domain object property mapped to not null column etc..)

          good luck with your integration testing.

          Comment

          Working...
          X