2010-05-13 4 views
3

Я выполняю модульное тестирование, и я ожидаю, что все данные, переданные в базу данных MySQL, будут отброшены ... но это не так. Данные фиксируются, хотя мой журнал показывает, что происходит откат. Я боролся с этим пару дней, поэтому моя настройка изменилась совсем немного, вот моя текущая настройка.Почему транзакции не откатываются при использовании 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> 

Я читал об этой проблеме, и я уже проверил, чтобы гарантировать, что таблицы базы данных MySQL являются настройки для использования InnoDB. Также у меня есть удалось успешно выполнить откат транзакций за пределами моего набора тестов. Так что это должна быть некоторая неправильная настройка с моей стороны.

Любая помощь будет принята с благодарностью :)

ответ

11

Проблема оказалась в том, что соединение было автоматическим совершением ПЕРЕД последующей транзакцией. Я должен был изменить свой DataSource боб, чтобы включать в себя свойство 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

Я надеюсь, что я прав, и что это просто один. Вам не хватает аннотации @Transactional на вашем тестовом классе. Это означает, что сам метод теста не выполняется в транзакции, и, следовательно, откат не требуется. Надеюсь это поможет.

+0

Я добавил аннотацию @Transactional, и она по-прежнему совершает транзакции :( – Trevor

+0

Ради тщательности ... как упоминалось ранее, я несколько раз менял настройки, и установка, которую я опубликовал выше, была не показывая в журналах, что транзакции откатывались ... когда я добавил аннотацию @Transactional, теперь она показывает, что транзакции катятся назад в журналах, но они все еще поступают в БД. У меня также был чтобы немного настроить мои библиотеки, мне пришлось отследить версию 3.2 файла asm.jar, поскольку я получал исключение «метод не найден» для библиотеки ASM. – Trevor

+0

Trevor, если у вас есть какие-либо транзакционные аннотации или элементы управления в самой службе пользователя. Конец может быть вызван значением REQUIRES_NEW распространения где-то в цепочке транзакций. Еще один тест, который я запускал, - просто вставить запись, используя DAO пользователя непосредственно в th DB, используя транзакционный тест и убедиться, что он откатывается. Если ничего не происходит с транзакцией, настроенной в спящем режиме. Можете ли вы предоставить более подробную информацию о том, что делает служба? – Gennadiy

5

Для меня defaultAutoCommit и @Transactional не помогло. Я должен был изменить дб типа для InnoDB

+3

InnoDB на самом деле является требованием для транзакций в MySQL; тип db по умолчанию не поддерживает их. –

0

Другим способом решить вашу проблему:

Вместо использование:

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

, который создает таблицу MyISAM по умолчанию, следовательно, не поддерживающие транзакции

Попытайтесь использовать

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

, который создает таблицы InnoDB, и таким образом поддерживает транзакции.

1

Это должен быть использован

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

TransactionalTestExecutionListener содержит isRollback(), который откаты в транзакции после метода испытаний.

Смежные вопросы