Luckyly for us we can achive that easily with Junit, Spring, Maven and H2. We will use an in-memory database that Spring will create and populate for us before the tests. The database will always be in a known state before and while running the tests, so we don't get nasty fails because of inconsistent data.
pom configuration
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<dependency> | |
<groupId>junit</groupId> | |
<artifactId>junit</artifactId> | |
<version>${junit.version}</version> | |
<scope>test</scope> | |
</dependency> | |
<dependency> | |
<groupId>javax.transaction</groupId> | |
<artifactId>jta</artifactId> | |
<version>1.1</version> | |
</dependency> | |
<dependency> | |
<groupId>com.h2database</groupId> | |
<artifactId>h2</artifactId> | |
<version>1.4.187</version> | |
</dependency> | |
<dependency> | |
<groupId>org.springframework</groupId> | |
<artifactId>spring-test</artifactId> | |
<version>${spring.version}</version> | |
<scope>test</scope> | |
</dependency> | |
<dependency> | |
<groupId>org.springframework</groupId> | |
<artifactId>spring-context</artifactId> | |
<version>${spring.version}</version> | |
</dependency> | |
<dependency> | |
<groupId>org.springframework</groupId> | |
<artifactId>spring-orm</artifactId> | |
<version>${spring.version}</version> | |
<scope>compile</scope> | |
</dependency> | |
<dependency> | |
<groupId>org.springframework</groupId> | |
<artifactId>spring-tx</artifactId> | |
<version>${spring.version}</version> | |
<scope>compile</scope> | |
</dependency> | |
<dependency> | |
<groupId>org.springframework</groupId> | |
<artifactId>spring-aop</artifactId> | |
<version>${spring.version}</version> | |
</dependency> | |
<dependency> | |
<groupId>org.springframework</groupId> | |
<artifactId>spring-test</artifactId> | |
<version>${spring.version}</version> | |
<scope>test</scope> | |
</dependency> | |
<dependency> | |
<groupId>org.springframework</groupId> | |
<artifactId>spring-beans</artifactId> | |
<version>${spring.version}</version> | |
</dependency> | |
..... | |
<plugins> | |
<plugin> | |
<version>2.19</version> | |
<groupId>org.apache.maven.plugins</groupId> | |
<artifactId>maven-surefire-plugin</artifactId> | |
</plugin> | |
</plugins> |
test-config.xml
In your src/test/resources create a file named test-config.xml.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<beans xmlns="http://www.springframework.org/schema/beans" | |
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
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-4.0.xsd"> | |
<bean id="entityManagerFactory" autowire="byName" | |
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> | |
<!-- <property name="dataSource" ref="wiklimbDataSource" /> --> | |
<property name="persistenceUnitName" value="wiklimb" /> | |
<property name="dataSource" ref="dataSource" /> | |
<property name="persistenceXmlLocation" value="classpath:META-INF/h2-persistence.xml" /> | |
<property name="jpaVendorAdapter"> | |
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> | |
</bean> | |
</property> | |
</bean> | |
<context:component-scan base-package="org.wiklimb.dao,org.wiklimb.service" /> | |
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> | |
<property name="entityManagerFactory" ref="entityManagerFactory" /> | |
</bean> | |
<!-- to get the entity manager --> | |
<tx:annotation-driven transaction-manager="transactionManager" /> | |
<jdbc:embedded-database id="dataSource" type="H2"> | |
<jdbc:script location="classpath:test.sql" /> | |
<jdbc:script location="classpath:data.sql" /> | |
</jdbc:embedded-database> | |
</beans> |
h2-persistence.xml
You also need to create the file src/test/resources/META-INF/h2-persistence.xml. Notice that there are no connection configuration on the persistence file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0"?> | |
<persistence xmlns="http://java.sun.com/xml/ns/persistence" | |
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" | |
version="2.0"> | |
<persistence-unit name="wiklimb" transaction-type="RESOURCE_LOCAL"> | |
<provider>org.hibernate.ejb.HibernatePersistence</provider> | |
<class>your classes here</class> | |
<properties> | |
<property name="hibernate.show_sql" value="true" /> | |
<property name="hibernate.archive.autodetection" value="" /> | |
</properties> | |
</persistence-unit> | |
</persistence> |
Database for testing
Create a test.sql and a data.sql files with the ddl and the data for your tests. Notice that h2 sql has it's own markup so you may need adjust the sql generated from your db.
The tests
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@RunWith(SpringJUnit4ClassRunner.class) | |
@ContextConfiguration(locations = { "classpath:test-config.xml" }) | |
public class PartyServiceTest { | |
@Autowired | |
private PartyService service; | |
@Autowired | |
private NotificationService notService; | |
@Test | |
@Transactional | |
public void acceptReq(){ | |
service.acceptRequest(new Joinrequest(null, party, user), admin); | |
Assert.assertTrue(service.getPartyRequests(party).isEmpty()); | |
Assert.assertEquals(2,service.getPartyUsers(party).size()); | |
Assert.assertEquals(EventType.PARTY_REQUEST_ACCEPTED,notService.getLatestNotifications(1, 1).get(0).getType()); | |
} |
Using @Transactional
If you annotate a test with @Transactional the entire unit test will be inside one transaction thath will be rolledback after the test, keeping the database data clean after the test.
Service and DAO tip
If your Service layer is annotated with @Transactional and your Dao layer isn't (daos shouldn't have @Transactional) test just one layer on each test case. For example, if you are testing the PartyService don't use the PartyDAO for the asserts, as the PartyDAO won't see changes created at the service functions.
You can view a full working example in wrex https://github.com/konum/wrex/