Откат транзакции в тестах Spring JDBC - PullRequest
13 голосов
/ 29 октября 2010

Я пытаюсь получить откат транзакции JDBC при использовании Spring-test безуспешно. Когда я запускаю следующее обновление SQL всегда фиксируется.

package my.dao.impl;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import org.springframework.test.context.transaction.TransactionConfiguration;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.Statement;

@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class})
@ContextConfiguration(locations={"classpath:ApplicationContext-test-DAOs.xml"})
@TransactionConfiguration(defaultRollback = true)
public class ConfirmationMatchingDAOImplTest {

    @Autowired
    private DataSource dataSource;

    @Test
    public void shouldInsertSomething() throws Exception {
        final Connection connection = dataSource.getConnection();
        final Statement statement = connection.createStatement();
        statement.executeUpdate("insert into TEST_INSERT values (1, 'hello')");
        statement.close();
        connection.close();
    }
}

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/>
    <property name="url" value="jdbc:sqlserver://makeitfunky:1490;databaseName=fonzie"/>
    <property name="username" value="ralph"/>
    <property name="password" value="p0n1es_R_kew1"/>
</bean>

Что я делаю не так?

Кроме того, я использую слишком много аннотаций? Могу ли я сделать его чище?

Ответы [ 8 ]

17 голосов
/ 29 октября 2010

Если вы явно не настраиваете прослушиватели выполнения теста, используя аннотацию @TestExecutionListeners, Spring конфигурирует по умолчанию DependencyInjectionTestExecutionListener, DirtiesContextTestExecutionListener и TransactionalTestExecutionListener. TransactionalTestExecutionListener обеспечивает выполнение транзакционного теста с семантикой отката по умолчанию. Явно объявив @TestExecutionListeners в своем тестовом классе и исключив TransactionalTestExecutionListener из списка слушателей, вы отключаете поддержку транзакций.

Вы также должны добавить аннотацию @Transactional на уровне класса или метода.

Вы также должны использовать DataSourceUtils , чтобы получить транзакционное соединение, управляемое DataSourceTransactionManager.

2 голосов
/ 21 октября 2014

добавьте эту аннотацию, и в тестовых случаях отката не будет:

 @TransactionConfiguration(defaultRollback=false)

Моя аннотация выглядит так:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/../applicationContext.xml" })
@TransactionConfiguration(defaultRollback=true)
public class DBCreatorTest {
2 голосов
/ 31 августа 2014

Если вы используете метод не-xml, он работает хорошо, начиная с версии 3.1

@Transactional
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {TestDbConfig.class, SomeService.class})
public class SomeTest {

@Inject
private SomeService someService;

@PersistenceContext
private EntityManager em;

@Test
public void someTest() {}

Тестовая конфигурация принимает эту форму. Обратите внимание на @EnableTransactionManagement и тот факт, что вы можете объявить глобальный тест defaultRollback. Это становится особенно полезным для крупных проектов.

@Configuration
@PropertySource(value = "classpath:app.properties")
@EnableTransactionManagement
@TransactionConfiguration(defaultRollback = true)
public class TestDbConfig {

//read the parameters from properties
@Value("${hibernate.dialect:unset}")
private String hibernateDialect;

@Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
    return new PropertySourcesPlaceholderConfigurer();
}

@Bean
public PlatformTransactionManager transactionManager() {
    //for example
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(entityManagerFactoryBean().getObject());
    return transactionManager;
}

@Bean
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() {
    //set the datasource
    //set the JpaVendorAdapter
    //set the packagesToScan
    return some sort of LocalContainerEntityManagerFactoryBean;
}

@Bean
DataSource dataSource() {
    return dataSource from jndi or a DriverManagerDataSource();
}

}

1 голос
/ 29 октября 2010

Может быть, потому что у вас нет @Transactional для метода испытаний?

0 голосов
/ 17 мая 2019

После опробования множества вышеперечисленных комбинаций у меня сработала следующая настройка с полным откатом после успешного прохождения теста.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:datasource-context-test.xml"})
@TransactionConfiguration(defaultRollback = true)
@Transactional
public class DataAccessTest 
{


    @Test
    public void testSaveRecords()
    { ... }
}
0 голосов
/ 08 апреля 2014

Вам нужно добавить @Transactional на уровне класса. Как то так:

@TransactionConfiguration(transactionManager = "txManager",defaultRollback = true)
@Transactional

Здесь txManager - это идентификатор экземпляра или компонента менеджера транзакций из application context.

<!-- Transaction Manager -->
    <bean id="txManager"
          class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    <tx:annotation-driven transaction-manager="txManager" />
0 голосов
/ 21 февраля 2014

дополнительная информация:

для этой строки

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

Значением по умолчанию атрибута transaction-manager является "actionManager ".Этот атрибут требуется только в том случае, если идентификатор / имя бина компонентаactionManager не является «actionManager ».Так что вам просто нужно установить:

<tx:annotation-driven />
0 голосов
/ 11 февраля 2011

При использовании аннотации @ Transactional в Spring необходимо добавить следующую строку в файл конфигурации Spring:

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

Свойство менеджера транзакций содержит ссылку на bean-компонент менеджера транзакций, определенный в файле конфигурации Spring. Этот код указывает Spring использовать аннотацию @Transaction при применении перехватчика транзакций. Без этого аннотация @Transactional игнорируется, в результате чего транзакция не используется в вашем коде.

Источник на сайте IBM

...