Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 821 Vote(s) - 3.52 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Rollback transaction after @Test

#1
First of all, I've found a lot of threads on StackOverflow about this, but none of them really helped me, so sorry to ask possibly duplicate question.

I'm running JUnit tests using spring-test, my code looks like this

@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() {
}
...
}

My problem is that I want my tests to NOT influence other tests.
So I'd like to create something like rollback for each test.
I've searched a lot for this, but I've found nothing so far.
I'm using Hibernate and MySql for this
Reply

#2
Just add `@Transactional` annotation on top of your test:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"testContext.xml"})
@Transactional
public class StudentSystemTest {

By default Spring will start a new transaction surrounding your test method and `@Before`/`@After` callbacks, rolling back at the end. It works by default, it's enough to have some transaction manager in the context.

From: [*10.3.5.4 Transaction management*](

[To see links please register here]

) (bold mine):

> In the TestContext framework, transactions are managed by the TransactionalTestExecutionListener. Note that `TransactionalTestExecutionListener` is **configured by default**, even if you do not explicitly declare `@TestExecutionListeners` on your test class. To enable support for transactions, however, you must provide a `PlatformTransactionManager` bean in the application context loaded by `@ContextConfiguration` semantics. In addition, **you must declare `@Transactional` either at the class or method level for your tests**.
Reply

#3
The answers mentioning adding `@Transactional` are correct, but for simplicity you could just have your test class `extends AbstractTransactionalJUnit4SpringContextTests`.
Reply

#4
You can disable the Rollback:

@TransactionConfiguration(defaultRollback = false)

Example:

@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();
}
}
Reply

#5
I know, I am tooooo late to post an answer, but hoping that it might help someone. Plus, I just solved this issue I had with my tests. This is what I had in my test:


My test class

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "path-to-context" })
@Transactional
public class MyIntegrationTest

Context 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>

I still had the problem that, the database was not being cleaned up automatically.

Issue was resolved when I added following property to BasicDataSource

<property name="defaultAutoCommit" value="false" />

Hope it helps.
Reply

#6
You need to run your test with a Spring context and a transaction manager, e.g.,


@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
}
}

See chapter [`3.5.8. Transaction Management`][1] of the Spring reference for further details.

[1]:

[To see links please register here]

Reply

#7
In addition to adding `@Transactional` on `@Test` method, you also need to add `@Rollback(false)`
Reply

#8
_Aside:_ attempt to amend Tomasz Nurkiewicz's answer was rejected:
> This edit does not make the post even a little bit easier to read, easier to find, more accurate or more accessible. Changes are either completely superfluous or actively harm readability.
<!--http://stackoverflow.com/users/3045515/sambhav-sharma-->
<!--http://stackoverflow.com/users/987339/user987339-->
<!--http://stackoverflow.com/users/4694013/anoop-m-->

----------

Correct and permanent [link](

[To see links please register here]

) to the relevant section of documentation about integration testing.
> To enable support for transactions, you must configure a `PlatformTransactionManager` bean in the `ApplicationContext` that is loaded via `@ContextConfiguration` semantics.

```java
@Configuration
@PropertySource("application.properties")
public class Persistence {
@Autowired
Environment env;

@Bean
DataSource dataSource() {
return new DriverManagerDataSource(
env.getProperty("datasource.url"),
env.getProperty("datasource.user"),
env.getProperty("datasource.password")
);
}

@Bean
PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
}
```

> In addition, you must declare Spring’s `@Transactional` annotation either at the class or method level for your tests.

```java
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {Persistence.class, SomeRepository.class})
@Transactional
public class SomeRepositoryTest { ... }
```

> Annotating a test method with `@Transactional` causes the test to be run within a transaction that will, by default, be automatically rolled back after completion of the test. If a test class is annotated with `@Transactional`, each test method within that class hierarchy will be run within a transaction.
Reply

#9
As answered above by the top-liked answer, basically you only need to 2 things below to rollback the transaction takes place in test cases:

- add @Transactional on the test Class
- add **@Rollback** on the Test Case


In case it still doesn't work, kindly double check if your system is using multiple data sources, if so, you also need to specify the expected data source for the transaction based on which DB your SQL will connect to.

Code example:

@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(){
...
}

}
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through