JUnit Testing Spring Service and DAO (with In-Memory Database)

This post describes how to implement JUnit tests for a Spring Web Application’s Services and DAO. It is built on top of the Spring MVC-Service-DAO-Persistence Architecture Example. This example is available from Github in the Spring-Web-JPA-Testing directory.

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();
    }

}

We need to exclude the production configuration from package scanning (no ‘com.jverstry’ scanning):

@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

The above is often caused by the following maven dependency:

         <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-api</artifactId>
            <version>6.0</version>
            <type>jar</type>
         </dependency>

It should be replaced with:

           <dependency>
               <groupId>org.apache.geronimo.specs</groupId>
               <artifactId>geronimo-jpa_2.0_spec</artifactId>
               <version>1.1</version>
               <scope>provided</scope>
           </dependency>

Another error message is:

javax.validation.ValidationException: Unable to find a default provider

This is solved by adding the following maven dependency:

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>4.3.0.Final</version>
        </dependency>

More Spring related posts here.

Reference: JUnit Testing Spring Service and DAO (with In-Memory Database) from our JCG partner Jerome Versrynge at the Technical Notes blog.

Related Whitepaper:

Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expressions

Get ready to program in a whole new way!

Functional Programming in Java will help you quickly get on top of the new, essential Java 8 language features and the functional style that will change and improve your code. This short, targeted book will help you make the paradigm shift from the old imperative way to a less error-prone, more elegant, and concise coding style that’s also a breeze to parallelize. You’ll explore the syntax and semantics of lambda expressions, method and constructor references, and functional interfaces. You’ll design and write applications better using the new standards in Java 8 and the JDK.

Get it Now!  

One Response to "JUnit Testing Spring Service and DAO (with In-Memory Database)"

  1. Nir M says:

    Cool.You can also check out the following for “how to” JUnit tests + JPA + XML based Spring configuration:
    http://tech-drum.blogspot.com/2011/11/junit-testing-with-in-memory-dbs-jpa-on.html
    cheers

Leave a Reply


eight − = 2



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.

Sign up for our Newsletter

15,153 insiders are already enjoying weekly updates and complimentary whitepapers! Join them now to gain exclusive access to the latest news in the Java world, as well as insights about Android, Scala, Groovy and other related technologies.

As an extra bonus, by joining you will get our brand new e-books, published by Java Code Geeks and their JCG partners for your reading pleasure! Enter your info and stay on top of things,

  • Fresh trends
  • Cases and examples
  • Research and insights
  • Two complimentary e-books