Reputation: 16555
Here's my test:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:repositoryContextTest.xml" })
@Transactional
@TransactionConfiguration(defaultRollback = true)
public class SeasonITest {
@Autowired
private SeasonDao seasonDao;
@Test
public void createSeason() throws Exception {
Season season = new Season();
season.setName("2012");
seasonDao.createSeason(season);
}
and the dataSource in my bean configuration file
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost/tournament_system" />
<property name="username" value="root" />
<property name="password" value="root" />
<property name="defaultAutoCommit" value="false"/>
<property name="poolPreparedStatements" value="false"/>
<property name="maxOpenPreparedStatements" value="0"/>
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
When I run this test there a new record is created in my database.
How can I rollback this transaction?
This is the log output I see:
2012-06-15 15:00:02,173 [main] INFO - ionalTestExecutionListener -
Rolled back transaction after test execution for test context
[[TestContext@76db09 testClass = SeasonITest,
locations = array<String>['classpath:repositoryContextTest.xml'],
testInstance = org.toursys.repository.dao.SeasonITest@1265109,
testMethod = createSeason@SeasonITest, testException = [null]]]
UPDATE:
all answers below want to change logic or database engine what I dont want. So I am offering reputation point to the right answer:
Why when I have this: @TransactionConfiguration(defaultRollback = true)
in transaction configuration tests are not rolled back and how I can fix it ?
Upvotes: 5
Views: 9390
Reputation: 13240
Your Dao needs to be marked @Transactional.
Also annotate your test with:
@TestExecutionListeners(TransactionalTestExecutionListener.class) //Rolls back transactions by default
Upvotes: 0
Reputation: 4829
Try with following method after your test case logic.
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
Upvotes: 0
Reputation: 1903
On the surface, your code and configuration looks correct. However, could you please post your SeasonsDAO object. We would first need to verify that the SeasonsDAO is correctly configured for transactions.
SeasonsDAO needs to be participating in the same TransactionContext as your test case and there is no way to verify that with the code you posted.
Did you mark SeasonsDAO as @Transactional ?
If it is not, I am not sure how the TransactionProxyFactoryBean would be able to proxy and declaratively manage the transaction.
At a high level, spring uses the notion of proxying to perform many services such as transaction management.
If you mark something as @Transactional, Spring will dynamically create a proxy that will implement the same interfaces as your target class. Once it is proxied, a transaction interceptor will wrap method calls to your target class and decide whether to rollback or commit based on defaults or rules that you may specify.
Upvotes: 1
Reputation: 5160
AbstractTransactionalJUnit4SpringContextTests
Upvotes: 0
Reputation: 2396
Haha had this same thing happen to me like 3 days ago. Try adding transactionManager ="transactionManager" to your @contextConfiguration:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:PersistenceHelper-context.xml"})
@TransactionConfiguration(defaultRollback = true, transactionManager = "transactionManager")
@Transactional
Also, I am not 100% percent sure on this, but your XML file should follow the "*-context" format. Let me know if you would like to see my PersistenceHelper-context.xml file.
Upvotes: 0
Reputation: 2073
Please make sure you must need to declare:
<tx:annotation-driven transaction-manager="transactionManager" />
in your spring configuration file e.g. (applicationContext.xml).
As @Lieber already explained but more explanation is: MySQL Server (version 3.23-max and all versions 4.0 and above) supports transactions with the InnoDB transactional storage engine. InnoDB provides full ACID compliance. See Chapter 14, Storage Engines. For information about InnoDB differences from standard SQL with regard to treatment of transaction errors, see Section 14.3.13, “InnoDB Error Handling”.
The other nontransactional storage engines in MySQL Server (such as MyISAM) follow a different paradigm for data integrity called “atomic operations.” In transactional terms, MyISAM tables effectively always operate in autocommit = 1 mode. Atomic operations often offer comparable integrity with higher performance. So, MyISAM transactional storage engine always autocommit transaction.
Upvotes: 0
Reputation: 481
If you are using MySQL with MyISAM engine try switching to InnoDB.
For more complicated test you will probably need a mocking framework or DB recreation.
EDIT1: According to the documentation InnoDB is transactional with full ACID support while MyISAM has support for atomic operations. More reading: Transaction and Atomic Operation Differences
EDIT2: In @TransactionConfiguration the default value for defaultRollback is true, so instead of commenting the line you should add @TransactionConfiguration(defaultRollback=false)
Upvotes: 7
Reputation:
There's also other solutions for this:
This way you won't have to rollback your changes.
Upvotes: 0