Spring 3 Testing with JUnit 4. Using @ContextConfiguration and AbstractTransactionalJUnit4SpringContextTests

Looking in the Internet for a way to test my Spring 3 application, I found many articles that describe how to test your application by using JUnit. Most of them are incomplete examples that do not really work. With this article I will try to fill this gap and write a concise yet simple article on how to test a spring 3 application with Junit 4. Ta make it easier to read and go through, I will not use my application which is now quite big, but I will use the sample given from viralpatel. The link to download the project is:

http://viralpatel.net/blogs/download/spring/spring-3-mvc-series/Spring3HibernateMaven.zip

Download this application and import it into eclipse.

Execute the following in you db:

create database contact;
use contact;
CREATE TABLE CONTACTS
(
    id              INT PRIMARY KEY AUTO_INCREMENT,
    firstname    VARCHAR(30),
    lastname    VARCHAR(30),
    telephone   VARCHAR(15),
    email         VARCHAR(30),
    created     TIMESTAMP DEFAULT NOW()
);

Inside your pom.xml add the following dependencies:

<dependency>
			<groupId>org.springframework.data</groupId>
			<artifactId>spring-data-jpa</artifactId>
			<version>1.0.1.RELEASE</version>
		</dependency>
<dependency>
			<groupId>org.junit</groupId>
			<artifactId>com.springsource.org.junit</artifactId>
			<version>4.7.0</version>
			<scope>test</scope>
		</dependency>
<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>org.springframework.test</artifactId>
			<version>${org.springframework.version}</version>
			<scope>test</scope>
		</dependency>
		<dependency> <groupId>javax.transaction</groupId>
		 <artifactId>com.springsource.javax.transaction</artifactId>
		  <version>1.1.0</version> </dependency>

Also add the following for repositories:

<repositories>
		<repository>
			<id>com.springsource.repository.bundles.release</id>
			<name>SpringSource Enterprise Bundle Repository - SpringSource Releases</name>
			<url>http://repository.springsource.com/maven/bundles/release</url>
		</repository>
		<repository>
			<id>com.springsource.repository.bundles.external</id>
			<name>SpringSource Enterprise Bundle Repository - External Releases</name>
			<url>http://repository.springsource.com/maven/bundles/external</url>
		</repository>
		<repository>
			<id>com.springsource.repository.bundles.milestone</id>
			<name>SpringSource Enterprise Bundle Repository - SpringSource Milestones</name>
			<url>http://repository.springsource.com/maven/bundles/milestone</url>
		</repository>
		<repository>
			<id>com.springsource.repository.bundles.snapshot</id>
			<name>SpringSource Enterprise Bundle Repository - Snapshot Releases</name>
			<url>http://repository.springsource.com/maven/bundles/snapshot</url>
		</repository>
<repository>
			<id>repository.springframework.maven.release</id>
			<name>Spring Framework Maven Release Repository</name>
			<url>http://maven.springframework.org/release</url>
		</repository>
		<repository>
			<id>repository.springframework.maven.milestone</id>
			<name>Spring Framework Maven Milestone Repository</name>
			<url>http://maven.springframework.org/milestone</url>
		</repository>
		<repository>
			<id>repository.springframework.maven.snapshot</id>
			<name>Spring Framework Maven Snapshot Repository</name>
			<url>http://maven.springframework.org/snapshot</url>
		</repository>
		<repository>
			<id>jboss</id>
			<name>JBoss repository</name>
			<url>https://repository.jboss.org/nexus/content/repositories/releases</url>
		</repository>
	</repositories>

Under the directory src/test/java create the following package:
net.viralpatel.contact.form
Inside the package you just created create a class called:
AbstractContactTests

Under src/test/resources create the following:
net/viralpatel/contact/form
Inside there create the following file:
AbstractContactTests-context.xml

ATTENTION!!! Make sure that the directories, packages, classes and xml files are created exactly where mentioned above. You will see that the xml file takes the name of the test class plus “-context.xml” and that it is created under the same directory structure. This is important because spring automatically looks for the xml file with the specified name and also under the same directory.

Now insert the following content in the AbstractContactTests class:

package net.viralpatel.contact.form;
import net.viralpatel.contact.dao.ContactDAO;
import net.viralpatel.contact.service.ContactService;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;

@ContextConfiguration
public class AbstractContactTests extends AbstractTransactionalJUnit4SpringContextTests {
	@Autowired
	protected ContactDAO contact;
	@Autowired
	protected ContactService contactService;
	@Test
	public void sampleTest(){
			System.out.println("Number of rows is: " + contactService.listContact().size());
		System.out.println("Creating a new contact");
		Contact cont = new Contact();
		cont.setEmail("giannis@gmail.com");
		cont.setLastname("ntantis");
		cont.setFirstname("ioannis");
		cont.setTelephone("00306985587996");
		System.out.println("Before saving contact");
		contactService.addContact(cont);
		System.out.println("After saving contact. Id if contact is: " + cont.getId());
		System.out.println("Number of rows now is: " + contactService.listContact().size());
	}
}

The @ContextConfiguration annotation tells spring how to load and configure the application context. We could also tell spring where it would explicitely find the file, e.g. :
@ContextConfiguration(locations={“example/test-context.xml”}, loader=CustomContextLoader.class)

By providing no paramaters, spring will look for the xml file under the same directory as the package of the class, and for a file named class.name-context.xml (remember the HINT above).
Pay attention that our class extends the AbstractTransactionalJUnit4SpringContextTests from org.springframework.test.context.junit4. By extending this class, we give our methods transactional support at the class level. If we did not do this, and we wanted transactional support, we would have to either annotate our methods with @Transactional or configure our transaction manager with the @TransactionConfiguration annotation.
Inside the AbstractContactTests-context.xml put the following content:

<?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:context="http://www.springframework.org/schema/context" 
		xmlns:jdbc="http://www.springframework.org/schema/jdbc"
		xmlns:tx="http://www.springframework.org/schema/tx"
		xsi:schemaLocation="
			http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.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
			http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
	<context:property-placeholder location="classpath:jdbc.properties"/>
	<context:annotation-config/>
	<tx:annotation-driven/>
	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"
			p:driverClassName="com.mysql.jdbc.Driver" p:url="jdbc:mysql://localhost:3306/contact"
			p:username="root" p:password="123456"/>
	<bean id="sessionFactory"
		class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="configLocation">
			<value>classpath:hibernate.cfg.xml</value>
		</property>
		<property name="configurationClass">
			<value>org.hibernate.cfg.AnnotationConfiguration</value>
		</property>
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">${jdbc.dialect}</prop>
				<prop key="hibernate.show_sql">true</prop>
			</props>
		</property>
	</bean>
	<bean id="transactionManager"		class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>
	<bean id="contactDAO" class="net.viralpatel.contact.dao.ContactDAOImpl">
 </bean>
 <bean id="contactService" class="net.viralpatel.contact.service.ContactServiceImpl">
 </bean>

</beans>

Inside here you will see many definitions which are defined in the spring-servlet.xml . In my example they are the same with spring-servlet.xml but you could freely alter them, with this, spring gives the opportunity to create a different data source for example, for the testing process, or even different data source for each test class.

Now execute the AbstractContactTests class as a junit test. You should take the following output:

Hibernate: select contact0_.ID as ID0_, contact0_.EMAIL as EMAIL0_, contact0_.FIRSTNAME as FIRSTNAME0_, contact0_.LASTNAME as LASTNAME0_, contact0_.TELEPHONE as TELEPHONE0_ from CONTACTS contact0_
Number of rows is: 0
Creating a new contact
Before saving contact
Hibernate: insert into CONTACTS (EMAIL, FIRSTNAME, LASTNAME, TELEPHONE) values (?, ?, ?, ?)
After saving contact. Id if contact is: 2
Hibernate: select contact0_.ID as ID0_, contact0_.EMAIL as EMAIL0_, contact0_.FIRSTNAME as FIRSTNAME0_, contact0_.LASTNAME as LASTNAME0_, contact0_.TELEPHONE as TELEPHONE0_ from CONTACTS contact0_
Number of rows now is: 1

Thats all you need folks. If anything goes wrong, please do contact me and I will reply ASAP.

About these ads

9 Responses to Spring 3 Testing with JUnit 4. Using @ContextConfiguration and AbstractTransactionalJUnit4SpringContextTests

  1. Rafi says:

    mvn clean test

    ——————————————————-
    T E S T S
    ——————————————————-

    Results :

    Tests run: 0, Failures: 0, Errors: 0, Skipped: 0

    • Rafi says:

      what else i need to do to run the test case, i followed the steps as suggested above

    • giannisapi says:

      hi Rafi,

      Did you create your test case as shown in the example class AbstractContactTests ? You should need nothing more. Just right click this class in the eclipse and select “Run as Junit Test” or something similar..

      ask me if you need anything else..

  2. Nivedita says:

    can u give back the source in .gz or zip …. Ty

  3. Remus says:

    Thanks for this neat tutorial. It helped me.

  4. Hey I know this is off topic but I was wondering
    if you knew of any widgets I could add to my blog that automatically tweet my newest
    twitter updates. I’ve been looking for a plug-in like this for quite some time and was hoping maybe you would have some experience with something like this. Please let me know if you run into anything. I truly enjoy reading your blog and I look forward to your new updates.

  5. url shortner says:

    I’m impressed, I must say. Rarely do I encounter a blog that’s both equally educative
    and amusing, and without a doubt, you’ve hit the nail on the head. The problem is something too few men and women are speaking intelligently about. I’m very happy that I
    came across this in my search for something relating to this.

  6. This is very attention-grabbing, You are an excessively skilled blogger.
    I’ve joined your feed and look ahead to in search of more of your fantastic post. Also, I have shared your site in my social networks

  7. Quality articles or reviews is the main to attract the viewers to
    pay a visit the web site, that’s what this site is providing.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: