Reminder
- Test Fixture - The fixed state used as a baseline for running tests.
- Unit test - These tests verify that pieces of code (components) perform some functionalities as expected. In a Java environment, these are typically implemented at the class level.
- Integration test - Integration testing is any type of test checking that a set of interacting components perform expected functionalities together correctly.
Configuration
We need a JPA Hibernate configuration for in-memory testing:@Configuration @EnableTransactionManagement public class JpaTestConfig { @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(){ LocalContainerEntityManagerFactoryBean lcemfb = new LocalContainerEntityManagerFactoryBean(); lcemfb.setDataSource(this.dataSource()); lcemfb.setPackagesToScan(new String[] {"com.jverstry"}); lcemfb.setPersistenceUnitName("MyTestPU"); HibernateJpaVendorAdapter va = new HibernateJpaVendorAdapter(); lcemfb.setJpaVendorAdapter(va); Properties ps = new Properties(); ps.put("hibernate.dialect", "org.hibernate.dialect.HSQLDialect"); ps.put("hibernate.hbm2ddl.auto", "create"); lcemfb.setJpaProperties(ps); lcemfb.afterPropertiesSet(); return lcemfb; } @Bean public DataSource dataSource(){ DriverManagerDataSource ds = new DriverManagerDataSource(); ds.setDriverClassName("org.hsqldb.jdbcDriver"); ds.setUrl("jdbc:hsqldb:mem:testdb"); ds.setUsername("sa"); ds.setPassword(""); return ds; } @Bean public PlatformTransactionManager transactionManager(){ JpaTransactionManager tm = new JpaTransactionManager(); tm.setEntityManagerFactory( this.entityManagerFactoryBean().getObject() ); return tm; } @Bean public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){ return new PersistenceExceptionTranslationPostProcessor(); } }
@Configuration @ComponentScan(basePackages = { "com.jverstry.Controller", "com.jverstry.DAO", "com.jverstry.Item", "com.jverstry.Service" }) public class TestConfig { @Bean public MyService getMyService() { return new MyServiceImpl(); } }
Spring Testing Tools
- @RunWith - This is a JUnit annotation allowing one to run a test with a different runner than the one provided by JUnit.
- SpringJUnit4ClassRunner - This is a JUnit test runner for Spring applications. Typically, test classes are annoted with @RunWith(SpringJUnit4ClassRunner.class).
- @ContextConfiguration - This annotation can be used to specify how to load an applicationContext in Spring test class. This can be configured via XML files or Java configuration objects.
Service Testing
The following class tests the createAndRetrieve() method of our injected MyService implementation:@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes={ JpaTestConfig.class, TestConfig.class }) public class MyServiceImplTest { @Autowired private MyService myService; @Test public void testCreateAndRetrieve() { MilliTimeItem retr = myService.createAndRetrieve(); assertNotNull(retr); } }
DAO Testing
The following class tests our DAO implementation. Our implementation is injected with an EntityManager created from our test configuration class defined above.@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes={ JpaTestConfig.class, TestConfig.class }) public class MyPersistenceDAOTest { @Autowired private MyPersistenceDAO myDAO; @Test public void testCreateMilliTimeItem() { // This operation should not throw an Exception long id = myDAO.createMilliTimeItem(); } @Test public void testGetMilliTimeItem() { long id = myDAO.createMilliTimeItem(); MilliTimeItem retr = myDAO.getMilliTimeItem(id); assertNotNull(retr); assertEquals(id,retr.getID()); } }
Caveat
When starting to write JUnit tests for Spring, one can come across the following error messages:Java.lang.ClassFormatError: Absent Code attribute in method that is not native or abstract in class file javax/validation/Validation
<dependency> <groupId>javax</groupId> <artifactId>javaee-api</artifactId> <version>6.0</version> <type>jar</type> </dependency>
<dependency> <groupId>org.apache.geronimo.specs</groupId> <artifactId>geronimo-jpa_2.0_spec</artifactId> <version>1.1</version> <scope>provided</scope> </dependency>
javax.validation.ValidationException: Unable to find a default provider
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>4.3.0.Final</version> </dependency>
For Spring MVC Controller JUnit testing, see here • More Spring related posts here.
Nice Note, but I'm still looking for the persistence.xml, where is it in github ? thank you ( I'm using the web interface in github )
ReplyDeleteJPATestConfig replaces persistence.xml. All the configuration information is provided in code.
ReplyDeleteit is strange to use it test my code. the test work well and looks good if i put @Service in the interface class. but on live system with Tomcat 7, my code only work well if i put @Service in the implemented class
ReplyDelete