Откат транзакции после @Test
Во-первых, я обнаружил множество тем в Stackru по этому поводу, но ни одна из них мне не помогла, так что извините, возможно, задаю двойной вопрос.
Я запускаю тесты JUnit с использованием spring-test, мой код выглядит так
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {})
public class StudentSystemTest {
@Autowired
private StudentSystem studentSystem;
@Before
public void initTest() {
// set up the database, create basic structure for testing
}
@Test
public void test1() {
}
...
}
Моя проблема в том, что я хочу, чтобы мои тесты НЕ влияли на другие тесты. Поэтому я хотел бы создать что-то вроде отката для каждого теста. Я много искал для этого, но пока ничего не нашел. Я использую Hibernate и MySql для этого
8 ответов
Просто добавь @Transactional
аннотация поверх вашего теста:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"testContext.xml"})
@Transactional
public class StudentSystemTest {
По умолчанию Spring запускает новую транзакцию вокруг вашего метода тестирования и @Before
/ @After
обратные вызовы, откат в конце. Он работает по умолчанию, достаточно иметь некоторый менеджер транзакций в контексте.
С: 10.3.5.4 Управление транзакциями (жирный рудник):
В платформе TestContext транзакции управляются TransactionalTestExecutionListener. Обратите внимание, что
TransactionalTestExecutionListener
настроен по умолчанию, даже если вы явно не объявляете@TestExecutionListeners
на вашем тестовом классе. Однако, чтобы включить поддержку транзакций, вы должны предоставитьPlatformTransactionManager
бин в контексте приложения, загруженного@ContextConfiguration
семантика. Кроме того, вы должны объявить@Transactional
либо на уровне класса или метода для ваших тестов.
В сторону : попытка изменить ответ Томаша Нуркевича была отклонена:
Это изменение не делает сообщение даже немного легче для чтения, легче найти, более точным или более доступным. Изменения либо полностью излишни, либо активно вредят читабельности.
Правильная и постоянная ссылка на соответствующий раздел документации об интеграционном тестировании.
Чтобы включить поддержку транзакций, вы должны настроить
PlatformTransactionManager
боб вApplicationContext
загружается через@ContextConfiguration
семантика.
@Configuration @PropertySource ("application.properties") народный класс @Autowired Окружающая среда; @Bean DataSource dataSource() { вернуть новый DriverManagerDataSource( env.getProperty("datasource.url"), env.getProperty("datasource.user"), env.getProperty("datasource.password")); } @Bean PlatformTransactionManager TransactionsManager() { вернуть новый DataSourceTransactionManager(dataSource()); } }
Кроме того, вы должны объявить Spring
@Transactional
аннотации на уровне класса или метода для ваших тестов.
@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (classes = {Persistence.class, SomeRepository.class}) @Transactional открытый класс SomeRepositoryTest { ... }
Аннотирование метода испытаний с
@Transactional
вызывает выполнение теста в транзакции, которая по умолчанию автоматически откатывается после завершения теста. Если тестовый класс помечен@Transactional
каждый тестовый метод в этой иерархии классов будет выполняться внутри транзакции.
Ответы с упоминанием добавления @Transactional
правильно, но для простоты вы могли бы просто иметь свой тестовый класс extends AbstractTransactionalJUnit4SpringContextTests
,
Помимо добавления @Transactional
на @Test
метод, вам также необходимо добавить @Rollback(false)
Я знаю, я слишком поздно, чтобы опубликовать ответ, но надеюсь, что это может кому-то помочь. Плюс, я только что решил эту проблему с моими тестами. Вот что у меня было в моем тесте:
Мой тестовый класс
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "path-to-context" })
@Transactional
public class MyIntegrationTest
Контекст xml
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
У меня все еще была проблема, что база данных не очищалась автоматически.
Проблема была решена, когда я добавил следующее свойство в BasicDataSource
<property name="defaultAutoCommit" value="false" />
Надеюсь, поможет.
Вам нужно запустить свой тест с контекстом спринта и менеджером транзакций, например,
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"/your-applicationContext.xml"})
@TransactionConfiguration(transactionManager="txMgr")
public class StudentSystemTest {
@Test
public void testTransactionalService() {
// test transactional service
}
@Test
@Transactional
public void testNonTransactionalService() {
// test non-transactional service
}
}
См главу 10. Testing
весны ссылки для получения дополнительной информации.
Как было сказано выше в ответе, получившем наибольшее количество лайков, по сути, вам нужно всего лишь 2 вещи ниже, чтобы откат транзакции происходил в тестовых случаях:
- добавьте @Transactional в тестовый класс
- добавьте @Rollback в тестовый пример
Если это по-прежнему не работает, дважды проверьте, использует ли ваша система несколько источников данных. Если да, вам также необходимо указать ожидаемый источник данных для транзакции в зависимости от того, к какой БД будет подключаться ваш SQL.
Пример кода:
@SpringBootTest(classes = Sample.class)
@Transactional(transactionManager = "txManagerXX") // specify txManager here if your system uses multiple sources
public class SampleTest {
@Test
@Rollback
public void test_case_1(){
...
}
}
Вы можете отключить откат:
@TransactionConfiguration(defaultRollback = false)
Пример:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@Transactional
@TransactionConfiguration(defaultRollback = false)
public class Test {
@PersistenceContext
private EntityManager em;
@org.junit.Test
public void menge() {
PersistentObject object = new PersistentObject();
em.persist(object);
em.flush();
}
}