2010-05-13 13 views
3

Je fais des tests unitaires et j'espère que toutes les données validées dans la base de données MySQL seront annulées ... mais ce n'est pas le cas. Les données sont en cours de validation, même si mon journal montrait que la restauration était en cours. Je me suis battue avec ça pendant quelques jours, donc mon installation a beaucoup changé, voici ma configuration actuelle.Pourquoi les transactions ne sont pas annulées lors de l'utilisation de SpringJUnit4ClassRunner/MySQL/Spring/Hibernate

LoginDAOTest.java:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations={"file:web/WEB-INF/applicationContext-test.xml", "file:web/WEB-INF/dispatcher-servlet-test.xml"}) 
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true) 
public class UserServiceTest { 

    private UserService userService; 

    @Test 
    public void should_return_true_when_user_is_logged_in() 
      throws Exception 
    { 
    String[] usernames = {"a","b","c","d"}; 

    for (String username : usernames) 
    { 
     userService.logUserIn(username); 
     assertThat(userService.isUserLoggedIn(username), is(equalTo(true))); 
    } 
    } 

ApplicationContext-Text.xml:

<?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:aop="http://www.springframework.org/schema/aop" 
     xmlns:tx="http://www.springframework.org/schema/tx" 
     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
     http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd 
     http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> 

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> 
      <property name="driverClassName" value="com.mysql.jdbc.Driver"/> 
      <property name="url" value="jdbc:mysql://localhost:3306/******"/> 
      <property name="username" value="*****"/> 
      <property name="password" value="*****"/> 
    </bean> 

    <tx:annotation-driven transaction-manager="transactionManager"/> 

    <bean id="userService" class="Service.UserService"> 
    <property name="userDAO" ref="userDAO"/> 
    </bean> 

    <bean id="userDAO" class="DAO.UserDAO"> 
    <property name="hibernateTemplate" ref="hibernateTemplate"/> 
    </bean> 

    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> 
    <property name="dataSource" ref="dataSource"/> 
    <property name="mappingResources"> 
     <list> 
     <value>/himapping/User.hbm.xml</value> 
     <value>/himapping/setup.hbm.xml</value> 
     <value>/himapping/UserHistory.hbm.xml</value> 
     </list> 
    </property> 
    <property name="hibernateProperties"> 
     <props> 
     <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> 
     <prop key="hibernate.show_sql">true</prop> 
     </props> 
    </property> 
    </bean> 

    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager" 
      p:sessionFactory-ref="sessionFactory"/> 

    <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate"> 
    <property name="sessionFactory"> 
     <ref bean="sessionFactory"/> 
    </property> 
    </bean> 

</beans> 

Je suis en train de lire sur la question, et je l'ai déjà vérifié que les tables de base de données MySQL sont configurer pour utiliser InnoDB. En outre, j'ai été en mesure de mettre en œuvre avec succès l'annulation des transactions en dehors de ma suite de tests. Donc, cela doit être une sorte de configuration incorrecte de ma part.

Toute aide serait grandement apprécié :)

Répondre

11

Le problème s'est avéré être que la connexion était auto-validant AVANT que la transaction puisse être annulée. Je devais changer mon grain de dataSource pour inclure une propriété defaultAutoCommit:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> 
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/> 
    <property name="url" value="jdbc:mysql://localhost:3306/test"/> 
    <property name="username" value="root"/> 
    <property name="password" value="Ecosim07"/> 
    <property name="defaultAutoCommit" value="false" /> 
</bean> 
0

J'espère que je suis bien et que c'est simple. Il vous manque l'annotation @Transactional sur votre classe de test. Cela signifie que la méthode de test elle-même n'est pas exécutée dans une transaction et qu'il n'y a donc rien à annuler. J'espère que cela t'aides.

+0

J'ai ajouté l'annotation @Transactional et il commet toujours les transactions :( – Trevor

+0

Pour être complet ... comme mentionné précédemment, j'ai changé mon installation plusieurs fois, et la configuration que j'ai posté ci-dessus était ne montre pas dans les journaux que les transactions étaient annulées ... lorsque j'ai ajouté l'annotation @Transactional, cela montre maintenant que les transactions sont en train de revenir dans les journaux, mais il est toujours en train de valider la base de données. Pour modifier un peu mes bibliothèques, j'ai dû rechercher la version 3.2 du fichier asm.jar, car j'obtenais une exception «méthode non trouvée» pour la bibliothèque ASM. – Trevor

+0

Trevor, par hasard, avez-vous des annotations ou des contrôles transactionnels dans le service de l'utilisateur lui-même. La validation peut être due à une valeur de propagation REQUIRES_NEW quelque part sur la chaîne de transactions. Un autre test que je voudrais exécuter consiste simplement à insérer un enregistrement en utilisant l'utilisateur DAO directement dans la base de données en utilisant un test transactionnel et assurez-vous qu'il est en train de revenir en arrière. Si ce n'est pas le cas, la transaction est configurée dans Hibernate. Pouvez-vous fournir plus de détails sur ce que le service fait? – Gennadiy

5

Pour moi defaultAutoCommit et @Transactional n'a pas aidé. Je devais changer db de type à InnoDB

+3

InnoDB est en fait une exigence pour les transactions dans MySQL; le type db par défaut ne les supporte pas. –

0

Une autre façon de résoudre votre problème:

Au lieu d'utiliser:

<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> 

, ce qui crée une table MyISAM par défaut, donc ne supportant pas les transactions

Essayez d'utiliser

<prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop> 

, ce qui crée des tables InnoDB, et jeu. s prend en charge les transactions.

1

Ce doit être utilisé

@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true) 
@TestExecutionListeners({ TransactionalTestExecutionListener.class }) 
@Transactional 

TransactionalTestExecutionListener contient isRollback() qui rollbacks la transaction après la méthode d'essai.