Fortunately, if you are building such an application using Spring Framework and using JPA as a way to persistent/access your data (or using Spring Data), there are some easy ways to perform such JUnit tests against your data access layer.
The basic idea to implement such tests is to use an in-memory database. Such an in-memory database can be constructed with a set of predefined SQL statements/scripts.
Here's a simple example to illustrate the idea. This example is based on the previous Simple JPA example using Spring Framework.
In that example, we've created a data access object (DAO) for the entity User - UserDao. Here we will create the JUnit test case for the two methods (getNameStartsWith, and save). The test code looks like below:
[UserDaoTest.java]
package com.mytechtip.example.springjpatest; import static org.junit.Assert.*; import java.util.Calendar; import java.util.List; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.transaction.annotation.Transactional; @RunWith(org.springframework.test.context.junit4.SpringJUnit4ClassRunner.class) @ContextConfiguration(locations="classpath:beans-test.xml") @Transactional public class UserDaoTest { @Autowired UserDao userDao; @Before public void setUp() throws Exception { } @After public void tearDown() throws Exception { } @Test public void testGetNameStartsWith() { List<User> list = userDao.getNameStartsWith("J"); assertEquals(1, list.size()); User user = list.get(0); System.out.println(user.getId()+":"+user.getName() + ":" + user.getDob()+":"+user.getAddress()); assertEquals("Jack", user.getName()); } @Test public void testSave() { User u = new User(); u.setAddress("my address"); u.setName("John Smith"); Calendar cal = Calendar.getInstance(); cal.clear(); cal.set(2000, 0, 1); u.setDob(cal.getTime()); userDao.save(u); List<User> list = userDao.getNameStartsWith("J"); assertEquals(2, list.size()); User user = list.get(1); System.out.println(user.getId()+":"+user.getName() + ":" + user.getDob()+":"+user.getAddress()); assertEquals("John Smith", user.getName()); assertEquals(cal.getTime(), u.getDob()); } }
The annotations of the test class plays an important role. It specifies a different beans configuration file ("classpath:beans-test.xml") just for testing. This file should exist in your test source folder as it is only used for unit testing. The content of the beans configuration file is shown as below:
[beans-test.xml]
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd "> <context:component-scan base-package="com.mytechtip.example.springjpatest"> </context:component-scan> <tx:annotation-driven /> <bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory" /> </bean> <bean id='entityManagerFactory' class='org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean'> <property name="persistenceUnitName" value="spring-jpa-test" /> <property name='dataSource' ref='dataSource' /> <property name="jpaPropertyMap"> <map> <entry key="eclipselink.weaving" value="false" /> </map> </property> </bean> <jdbc:embedded-database id="dataSource"> <jdbc:script location="classpath:create-db.sql" /> <jdbc:script location="classpath:create-data.sql" /> </jdbc:embedded-database> </beans>
Compared with the previous beans configuration file that specifies an actual hsqldb data source, this beans configuration file creates embedded database using two sql files as the data source. The contents of the two sql files are shown as below. They can be edited in accordance with the junit test case mentioned above.
[create-db.sql]
insert into user(id, name, dob) values (1, 'Jack', '1999-12-31');
[create-data.sql]
CREATE TABLE user (ID BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1 INCREMENT BY 1) NOT NULL, ADDRESS VARCHAR(255), DOB DATE, NAME VARCHAR(255), PRIMARY KEY (ID));
The folder/file structure of the project is like the following. This is a maven project which has all the dependency defined in the pom.xml. And now you can download this example project from github and try it out by yourself.

