3

I have a MySQL database created and filled with test-purpose rows. I want to do my DAO unit tests on this database. Each @Test is @Transactional so a rollback is done after each test. Unfortunately, it is not working as changes are still made to my database.

I'm loading my Spring configuration with the following context.xml

<beans xmlns="http://www.springframework.org/schema/beans"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns:jdbc="http://www.springframework.org/schema/jdbc"
            xsi:schemaLocation="http://www.springframework.org/schema/beans
                                                    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                                                    http://www.springframework.org/schema/jdbc
                                                    http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd"
            xmlns:tx="http://www.springframework.org/schema/tx">

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />  
        <property name="url" value="jdbc:mysql://localhost:3306/push_test" />  
        <property name="username" value="push_dao" />  
        <property name="password" value="pushpassword" />
    </bean>

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
      <property name="dataSource"  ref="dataSource" />    
    </bean>

    <bean id="userPushDAO" class="my.package.userPushDAOImpl">
         <property name="dataSource" ref="dataSource"/>
    </bean>
</beans>

This stackoverflow issue said that I

must provide a PlatformTransactionManager bean in the application context

But even with it (it's the transactionManager in my context) nothing happens, my database is still modified and not rollbacked.

Here is my DAO test class

public class UtilisateurPushDAOImplTest {

    private static ApplicationContext ctx;

    private static UserPushDAO userPushDAO;


    @BeforeClass
    public static void doSetup() {
        ctx = new ClassPathXmlApplicationContext("context.xml");
        userPushDAO = (userPushDAO) ctx.getBean("userPushDAO");
    }

    @Test
    @Transactional
    public void test() {
         userPushDAO.deleteById("id");
    }
}

Am I missing something in my configuration or in my comprehension on how/what @Transactional should work/do ?

DaveyDaveDave
  • 9,821
  • 11
  • 64
  • 77
VictorGalisson
  • 635
  • 9
  • 27
  • I don't think you need the `@Transactional` at all. According to [the Spring docs](https://docs.spring.io/spring/docs/current/spring-framework-reference/testing.html#testing-tx), "By default, the framework will create and roll back a transaction for each test." – DaveyDaveDave Aug 21 '18 at 13:06
  • @DaveyDaveDave even without it, it's still modify my database :/ I think I can leave `@Transactional` there so my code is more understandable – VictorGalisson Aug 21 '18 at 13:17
  • @Transactional does not roll back everytime. It rolls back only when there is some exception in completing all the operation in a transaction . – DEVAS Aug 21 '18 at 13:21
  • @Devendra from Spring [documentation](https://docs.spring.io/spring/docs/current/spring-framework-reference/testing.html#testcontext-tx-enabling-transactions) it says it does : "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." – VictorGalisson Aug 21 '18 at 13:25
  • Ok I was not aware of this. Then just verify your class is annotated with spring junit runner. I could not see it in your code sample. As it is also in spring doc you provided @RunWith(SpringRunner.class) – DEVAS Aug 21 '18 at 13:31
  • 1
    `@Transactional` on tests will only work with the `SpringRunner` as a Unit test runner. It doesn't work if you create the application context yourself. – M. Deinum Aug 21 '18 at 13:32
  • @Devendra the issue is when adding the `@RunWith` annotation, I can't load the ApplicationContext anymore as I get a `java.lang.IllegalStateException: Failed to load ApplicationContext`. I will try to fix this and come back to you. – VictorGalisson Aug 21 '18 at 13:41
  • @M.Deinum oh ok, I will try to load it differently then. I used this method of loading as it was the one working for me. I will try again with an other one – VictorGalisson Aug 21 '18 at 13:43
  • @M.Deinum as you said, it was because I was creating the application myself and had no `SpringRunner`, thanks ! – VictorGalisson Aug 21 '18 at 14:17

1 Answers1

1

As @M.Deinum posted in the comment section,

@Transactional on tests will only work with the SpringRunner as a Unit test runner.

It doesn't work if you create the application context yourself.

Also don't forget to add the transaction schema into the context.xml to be able to load your context file correctly.

DAO test class

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:/context.xml"})
public class UserPushDAOImplTest {
    
    @Resource(name="userPushDAO")
    private UserPushDAO userPushDAO;

    @Test
    @Transactional
    public void test() {
         userPushDAO.deleteById("id");
    }
}

context.xml

<beans xmlns="http://www.springframework.org/schema/beans"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns:jdbc="http://www.springframework.org/schema/jdbc"
            xmlns:tx="http://www.springframework.org/schema/tx"
            xmlns:context="http://www.springframework.org/schema/context"
            xsi:schemaLocation="http://www.springframework.org/schema/beans
                                http://www.springframework.org/schema/beans/spring-beans.xsd
                                http://www.springframework.org/schema/jdbc
                                http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
                                http://www.springframework.org/schema/context
                                http://www.springframework.org/schema/context/spring-context.xsd">  

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />  
        <property name="url" value="jdbc:mysql://localhost:3306/push_test" />  
        <property name="username" value="push_dao" />  
        <property name="password" value="pushpassword" />
    </bean>
    
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource"  ref="dataSource" />    
    </bean>

    <bean id="userPushDAO" class="my.package.userPushDAOImpl">
        <property name="dataSource" ref="dataSource"/>
    </bean>
</beans>
Community
  • 1
  • 1
VictorGalisson
  • 635
  • 9
  • 27