views:

46

answers:

2

I'm trying to get JDBC transaction rollback when using Spring-test without success. When I run the following the SQL update is always committed.

package my.dao.impl;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import org.springframework.test.context.transaction.TransactionConfiguration;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.Statement;

@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class})
@ContextConfiguration(locations={"classpath:ApplicationContext-test-DAOs.xml"})
@TransactionConfiguration(defaultRollback = true)
public class ConfirmationMatchingDAOImplTest {

    @Autowired
    private DataSource dataSource;

    @Test
    public void shouldInsertSomething() throws Exception {
        final Connection connection = dataSource.getConnection();
        final Statement statement = connection.createStatement();
        statement.executeUpdate("insert into TEST_INSERT values (1, 'hello')");
        statement.close();
        connection.close();
    }
}

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/>
    <property name="url" value="jdbc:sqlserver://makeitfunky:1490;databaseName=fonzie"/>
    <property name="username" value="ralph"/>
    <property name="password" value="p0n1es_R_kew1"/>
</bean>

What am I doing wrong?

Additionally, am I using too many annotations? Can I make it a bit cleaner?

+1  A: 

Could it be because you do not have an @Transactional for the test method?

Raghuram
I added @Transactional and it had no effect. I also added @Rollback and it still had no effect.
Synesso
+1  A: 

If you do not explicitly configure test execution listeners using the @TestExecutionListeners annotation, Spring configures by default DependencyInjectionTestExecutionListener, DirtiesContextTestExecutionListener, and TransactionalTestExecutionListener. TransactionalTestExecutionListener provides transactional test execution with default rollback semantics. By explicitly declaring @TestExecutionListeners on your test class and omitting TransactionalTestExecutionListener from the listeners list, you are disabling transactional support.

You must also add the @Transactional annotation at the class or method level.

You must also use DataSourceUtils to get a transactional Connection managed by DataSourceTransactionManager.

Jim Huang
I removed @TestExecutionListeners and added @Transactional. I then had to add a transactionManager bean to the app-context (DataSourceTransactionManager). Txn was not rolled back so I added @TransactionConfiguration(defaultRollback=true). Txn was still not rolled back so I added @Rollback to the test method. Only then did I see Spring log that it was rolling back the txn, but the update still gets persisted to the DB. Something to do with SQL Server and its driver perhaps?
Synesso
Added DataSourceUtils to my answer.
Jim Huang
Ah, I didn't get notified of your last comment. In the meantime I have changed my context to wrap the datasource in a TransactionAwareDataSourceProxy. That worked. So there you go, two ways to do the same thing. Now to see which of these 7 annotations I can get rid of and still have the thing work.
Synesso