I found many people, including myself, struggling with creating test environment for web apps using Spring, Hibernate and Transactions. Sometimes there's a need to test your services in action without mock objects and so on. So how do you do that?
Here's main configuration class:
import java.util.Properties;
import org.hibernate.SessionFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBuilder;
import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
*
* @author MarcinG
*/
@Configuration
@EnableTransactionManagement
@ComponentScan(basePackages = {})
public class DataTestConfig {
@Bean
public SessionFactory sessionFactory() {
LocalSessionFactoryBuilder builder
= new LocalSessionFactoryBuilder(dataSource());
builder.configure("hibernate-test.cfg.xml");
return builder.buildSessionFactory();
}
private Properties getHibernateProperties() {
Properties prop = new Properties();
prop.put("hibernate.format_sql", "true");
prop.put("hibernate.show_sql", "true");
prop.put("hibernate.hbm2ddl.auto", "create-drop");
prop.put("hibernate.dialect",
"org.hibernate.dialect.HSQLDialect");
return prop;
}
@Bean(name = "dataSource")
public DriverManagerDataSource dataSource() {
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName("org.hsqldb.jdbcDriver");
ds.setUrl("jdbc:hsqldb:mem:test_db");
ds.setUsername("sa");
return ds;
}
@Bean
public HibernateTransactionManager transactionManager() {
return new HibernateTransactionManager(sessionFactory());
}
}
In my case I'm using Gradle, so I have file "hibernate-test.cfg.xml" inside Resources dir. It looks like that:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.pool_size">10</property>
<property name="hibernate.connection.autocommit">true</property>
<property name="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider</property>
<property name="hibernate.hbm2ddl.auto">create-drop</property><!-- creates the tables from the entites automatically -->
<property name="show_sql">true</property>
<property name="dialect">org.hibernate.dialect.HSQLDialect</property>
<mapping resource="pl/com/marcing/test/hibernate/Test.hbm.xml"/>
</session-factory>
</hibernate-configuration>
Now you create tests like this one:
/**
*
* @author Gensiub
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {DataTestConfig.class})
public class TestFieldInRaportService {
@Autowired
TestService testService;
/* service tests */
}
That service has @Transactional annotation. It uses DAO and so on. Test env will have in memory database which will work like a normal one. You can test whether you can retrieve previously saved objects and so on (no need for normal database).
Cheers!