Как откатить транзакцию базы данных при тестировании сервисов с помощью Spring в JUnit? - PullRequest
35 голосов
/ 12 ноября 2010

У меня нет проблем с тестированием DAO и сервисов, но когда я тестирую INSERT s или UPDATE s, я хочу откатить транзакцию и не влиять на мою базу данных.

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

Это мой тест:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:/META-INF/spring.cfg.xml")
@TransactionConfiguration(defaultRollback=true)
public class MyServiceTest extends AbstractJUnit38SpringContextTests  {
    @Autowired
    private MyService myService;

    @BeforeClass
    public static void setUpClass() throws Exception {
    }

    @AfterClass
    public static void tearDownClass() throws Exception {
    }

    @Test
    public void testInsert(){
        long id = myService.addPerson( "JUNIT" );
        assertNotNull( id );
        if( id < 1 ){
            fail();
        }
    }
}

Проблема в том, что этотест не пройден, так как транзакция была отменена, но вставка в порядке!Если я удаляю @TransactionConfiguration(defaultRollback=true), то тестовый проход, но новая запись будет вставлена ​​в базу данных.

@Test
@Transactional
@Rollback(true)
public void testInsert(){
    long id = myService.addPerson( "JUNIT" );
assertNotNull(id);
if( id < 1 ){
        fail();
    }
}

Теперь можно выполнить тестовый проход правильно, но откат игнорируется и запись вставляется в базу данных.Я пометил метод addPerson() внутри myService с помощью @Transactional, очевидно.Почему откат игнорируется?

Ответы [ 4 ]

30 голосов
/ 12 ноября 2010

Вам необходимо расширить границы транзакций до границ вашего метода тестирования.Вы можете сделать это, пометив свой метод тестирования (или весь класс тестирования) как @Transactional:

@Test 
@Transactional
public void testInsert(){ 
    long id=myService.addPerson("JUNIT"); 
    assertNotNull(id); 
    if(id<1){ 
        fail(); 
    } 
} 

Вы также можете использовать этот подход, чтобы убедиться, что данные были правильно записаны до отката:

@Autowired SessionFactory sf;

@Test 
@Transactional
public void testInsert(){ 
    myService.addPerson("JUNIT"); 
    sf.getCurrentSession().flush();
    sf.getCurrentSession().doWork( ... check database state ... ); 
} 
2 голосов
/ 12 ноября 2010

check

http://static.springsource.org/spring/docs/2.5.x/reference/testing.html

В частности, в разделе 8.3.4

Spring имеет несколько классов для тестирования, которые обертывают каждый тест в транзакции, поэтому DBне изменился.Вы можете изменить эту функциональность, если хотите.

Редактировать - в зависимости от ваших дополнительных сведений вы можете посмотреть

AbstractTransactionalJUnit38SpringContextTests на

http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/test/context/junit38/AbstractTransactionalJUnit38SpringContextTests.html

1 голос
/ 10 апреля 2014

Используйте следующую аннотацию перед классом:

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

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

Здесь 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" />

Добавьте ваш код в метод setUp(), он будет выполняться в начале теста, а последний код завершения должен быть помещен в метод teatDown(), который будет выполнен в конце. или вместо него можно использовать аннотации @Before и @After.

0 голосов
/ 17 апреля 2013

Если ваш метод

myService.addPerson("JUNIT"); 

аннотирован, как @Transactional, вы будете получать сообщения другого типа или ошибки, пытаясь это исправить.Так что вам лучше просто проверить методы DAO.

...