Весенний интеграционный тест с ручным управлением транзакциями
Я читал много постов и веток о тестировании интеграции со Spring, но ничего не может быть ни полезным, ни полезным.
Мы используем Spring 3.2.3 с Hibernate, Spring Data и базой данных Oracle. Для тестирования мы также используем DbUnit и Spring-test-dbunit. В рабочем коде транзакция запускается контроллером, а сама служба ничего не знает о транзакции.
Итак, вот мой тест:
@ContextConfiguration // ...
@ActiveProfiles // ...
@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({
DependencyInjectionTestExecutionListener.class,
DirtiesContextTestExecutionListener.class,
TransactionalTestExecutionListener.class,
ModifiedDbUnitTestExecutionListener.class })
@DbUnitConfiguration(databaseConnection = "oracleConnection")
@DatabaseSetup("/database/snapshot/snapshot.xml")
public class IntegrationTest extends AbstractTransactionalJUnit4SpringContextTests
{
@Test
public void sampleTest()
{
// transaction is already started
this.assertThatNewsContains(0);
News news1 = new News();
news1.setTitle("Test News 1");
News savedNews1 = this.newsService.save(news1);
Assert.assertTrue(savedNews1.getId() > 0);
News news2 = new News();
news2.setTitle("Test News 2");
News savedNews2 = this.newsService.save(news2);
Assert.assertTrue(savedNews2.getId() > 0);
News news3 = new News();
news3.setTitle("Test News 3");
News savedNews3 = this.newsService.save(news3);
Assert.assertTrue(savedNews3.getId() > 0);
// transaction commit should occur HERE
// @todo: HOW ?!
this.assertThatNewsContains(3);
}
private void assertThatNewsContains(int newsSize)
{
List<News> allNews = this.newsService.getNews();
Assert.assertEquals(newsSize, allNews.size());
}
}
Что я узнал, так это то, что если я аннотирую службу новостей с @Transactional(propagation=Propagation.REQUIRES_NEW)
тест работает нормально, но не так, как в рабочем режиме. @Transactional(propagation=Propagation.REQUIRED)
недостаточно, поскольку DbUnit-Spring-test сам по себе открывает транзакцию, и последнее подтверждает ошибку, так как транзакция еще не зафиксирована. Как я могу добиться, чтобы транзакция была зафиксирована ДО того, как будет выполнено последнее утверждение?
2 ответа
Я просто хотел показать, как мне наконец удалось выполнить некоторый код в отдельной транзакции.
Тебе нужно
@Autowired
private PlatformTransactionManager platformTransactionManager;
private TransactionTemplate transactionTemplate;
в вашем тестовом классе. Тогда вы можете сделать следующее:
this.transactionTemplate = new TransactionTemplate(this.platformTransactionManager);
// note that parameters passed to the transaction must be final!
final Object parameter = something;
Object returnedValue = this.transactionTemplate.execute(new TransactionCallback<Object>()
{
@Override
public Object doInTransaction(TransactionStatus status)
{
return doSomethingAndReturnAnObject(parameter);
}
}
);
Как указано в документации
http://springtestdbunit.github.io/spring-test-dbunit/
Если вы сконфигурировали тесты DBUnit для запуска с использованием DbUnitTestExecutionListener, а также используете TransactionalTestExecutionListener, у вас могут возникнуть проблемы с транзакциями, которые не запускаются до настройки данных или откатываются до того, как ожидаемые результаты могут быть проверены. Для поддержки тестов @Transactional с DBUnit вы должны использовать класс TransactionDbUnitTestExecutionListener.
И чтобы инициировать транзакцию, вы должны аннотировать свой тестовый метод или класс с помощью аннотации @Transactional, подобной этой.
@Test
@Transactional
public void sampleTest()
{