0
votes

I want to rollback database after each test but it doesn't work, I've tried different types of Transaction management configs. The createNewItem method object is still showing on other tests.

The goal of the rollback is to have the have exacly the same database objects and expected new ids on every test

ContextConfiguration:

 @Configuration
 @EnableJpaRepositories("se.system.repository")
 @EnableTransactionManagement
 public class ContextConfiguration{

@Bean(name = "hsqldb")
public DataSource InMemoryDataSource() {
    EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
    EmbeddedDatabase database = builder.setType(EmbeddedDatabaseType.HSQL)
            .addScript("classpath:se/system/sql/create-db.sql")
            .addScript("classpath:se/system/sql/insert-data.sql").build();

    return database;
}

@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory factory) {
    return new JpaTransactionManager(factory);
}


@Bean
public JpaVendorAdapter jpaVendorAdapter() {

    HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
    adapter.setDatabase(Database.HSQL);
    adapter.setShowSql(false);
    adapter.setGenerateDdl(false);
    return adapter;
}

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {

    LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
    factory.setDataSource(InMemoryDataSource());
    factory.setJpaVendorAdapter(jpaVendorAdapter());
    factory.setPackagesToScan("se.system.model");
    return factory;
}

Junit test with hsqldb:

 @RunWith(SpringJUnit4ClassRunner.class)
 @ContextConfiguration(classes = {ContextConfiguration.class })
 @TestExecutionListeners
 @Transactional
 public class ServiceTest {

@Rule
public ExpectedException thrown = ExpectedException.none();

private static Service service;

private static AnnotationConfigApplicationContext context;

@BeforeClass
public static void setup() {
    context = new AnnotationConfigApplicationContext();
    context.register(ContextConfiguration.class);
    context.scan("se.system");
    context.refresh();
    Service = context.getBean(Service.class);
}


@Test
public void createNewItem() {

    System.out.println(((List<Item>) service.getAllitem()).size());
    Item item = Service
            .saveOrUpdateItem(new Item("Title", "Description"));
    System.out.println(Item);
    assertEquals(new Long(4L), Item.getId());
}
1
Hi, Where have you set autocommit to false? - Curious
Hey, I was looking for that too, but I didn't find where to turn it to false so I thought it already was false by default. - T3rraform
Can you post the service class code with the method saveOrUpdateItem? - Patrick
Even if the test does roll back, i.e. un-inserts the Item object, the id generator won't roll back if it is generated by an identity column. So running the test twice on the same database will definitely fail in the second time if it succeeded the first time. - Turan Yüksel
Ok but the database object is still there after the test if I print them all out - T3rraform

1 Answers

0
votes

That’s how I usually annotate my test classes:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { JPAUnitTestConfiguration.class })
@Transactional //rollback if exception occurs during test method
@TransactionConfiguration(defaultRollback = true) //rollback at end of method
@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
public class FooBarTest {
}

Add @TransactionConfiguration(defaultRollback = true) to your test class.

My transaction configuration:

import java.sql.SQLException;

import javax.sql.DataSource;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import ch.ams.pois.repository.AuthTokenRepository;
import ch.ams.pois.repository.GroupRepository;
import ch.ams.pois.repository.InvitationRepository;
import ch.ams.pois.repository.LocationRepository;
import ch.ams.pois.repository.UserRepository;


@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = JPAConfiguration.JPA_REPOSITORIES_BASE_PACKAGES, 
includeFilters = @ComponentScan.Filter(value = { 
        UserRepository.class, LocationRepository.class, 
        GroupRepository.class, AuthTokenRepository.class, 
        InvitationRepository.class }, 
        type = FilterType.ASSIGNABLE_TYPE))
public class JPAUnitTestConfiguration extends JPAConfiguration {

    @Bean
    public DataSource dataSource() throws SQLException {
        EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
        return builder.setType(EmbeddedDatabaseType.H2).build();
    }
}

The dependencies for the persistence layer:

<dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jpa</artifactId>
            <version>1.3.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate.javax.persistence</groupId>
            <artifactId>hibernate-jpa-2.0-api</artifactId>
            <version>1.0.1.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>4.0.1.Final</version>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>1.3.173</version>
        </dependency>
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>9.2-1003-jdbc4</version>
        </dependency>