Skip to content

Testing persistence layer (starting with facelets part 3)

April 4, 2010

Testing is very important in software development and there are so many testing framework. In Java ecosystem the most popular is JUnit and TestNG. I prefer TestNG. When you want to write test, frist you must know what do you want to test. There are several kind of tests grouped by where they are added in the software development process (unit tests, integration tests, system tests, system integration test,regression tests, acceptance tests,…). This is the 3rd part of Starting with Facelets tutorial.
In the  first part I have made html template using facelets library for simple blog app. In second part I have made persistence layer using GenericDAO pattern. Now, I am gonna test DAO objects.


But before I start with writing tests I installed TestNG plugin for Eclipse. Here are instructions http://testng.org/doc/download.html. I have also created hibernate configuration file where I define my data source and other hibernate properties. For database engine I set HSQL. It’s good only for testing and suitable for using during development. In part two of this tutorial I used MySQL database and there were not hibernate configuration file(hibernate.cfg.xml file). I did this cause I just want to test simple CRUD methods and connection to database(no matter what is database engine). Just remember Generic DAO pattern make same interface for persistence layer no matter what database engine is used. This is hibernate.cfg.xml file.

<?xml version="1.0" encoding="UTF-8"?>
<!--<span class="hiddenSpellError" pre=""-->DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
                                         "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
 <session-factory name="sessionFactory">
  org.hsqldb.jdbcDriver
  <property name="hibernate.connection.username">sa</property>
  <property name="hibernate.dialect">org.hibernate.dialect.HSQLDialect</property>
  jdbc:hsqldb:data/testBase
  <property name="hibernate.show_sql">true</property>
  <property name="hibernate.hbm2ddl.auto">create-drop</property>
  <mapping class="demo.model.User"/>
  <mapping class="demo.model.Article"/>
  <mapping class="demo.model.Comment"/>
 </session-factory>
</hibernate-configuration>

It is similar like persistence.xml file. With tag I tell Hibernate which classes I mapped with annotations.  Why I didn’t define hibernate.cfg.xml file when I build persistence layer? I could do it simple and just inject that configuration in persitence.xml, but I configure all in persistence.xml cause app run in JBoss container and hiberante configuration nad mapping are loaded automaticly.
To run tests in TestNG you have to make testing.xml file where you specifie your test suit. Create test folder in META-INF file and create testing.xml file.

<!--<span class="hiddenSpellError" pre=""-->DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="Suite" verbose="1">
  <test name="HiberantePersistenceTest">
    <packages>
      <package name="test.persistence"/>
	 </packages>
  </test>
</suite>

In testing.xml I have define name of test (HibernatePesrirtenceTest) and package where are my test classes. So let’s go to writing classes. Create class GenericDAOTest in test.persistence package.

package test.persistence;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.cfg.Configuration;
import org.testng.Assert;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.Test;

public class GenericDAOTest extends Assert{
	public static SessionFactory factory;
	@BeforeSuite()
	public void configure(){
		Configuration conf= new AnnotationConfiguration().configure("META-INF/test/hibernate.cfg.xml");
		factory= conf.buildSessionFactory();
	}
	@Test
	public void isSessionExsist(){
		assertNotNull(factory.openSession());
	}

}

To write test method add @Test annotation below method. @BeforeSuite annotation annotate method which will be run before all tests in this suite have run. In configure method I build session factory using configurations in hiberante.cfg.xml file. is SessionExsist() method test is hiberante session created using session factory.  Class UserDAOTest extends GenericDAOTest cause I want to use session factory referenced with GenericDAOTest.

package test.persistence;

import org.hibernate.Transaction;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import demo.model.User;
import demo.persistence.implementation.UserDAOImpl;

public class UserDAOTest extends GenericDAOTest{
	private UserDAOImpl daoObject;
	private User testUser;

	@BeforeClass
	public void setUp(){
		daoObject=new UserDAOImpl();
		daoObject.setSession(GenericDAOTest.factory.openSession());
	}
	@BeforeMethod
	public void setUpTestUser(){
		testUser = new User();
	}
	@Test
	public void testDelete(){
		Transaction tr = daoObject.getSession().getTransaction();
		tr.begin();
		daoObject.save(testUser);//first save user in database
		daoObject.delete(testUser);//delete the user
		assertNull(daoObject.get(testUser.getId()));//check it is deleted
		tr.commit();
	}
	@Test
	public void testSave(){
		Transaction tr = daoObject.getSession().getTransaction();
		tr.begin();
		assertNotNull(daoObject.getSession());
		assertNull(daoObject.get(testUser.getId()));//check there aren't any user with given id in database
		daoObject.save(testUser);//save user
		assertNotNull(daoObject.get(testUser.getId()));//check that the user is persisted in database
		tr.commit();
	}
	@Test
	public void testGet(){
		Transaction tr = daoObject.getSession().getTransaction();
		tr.begin();
		daoObject.save(testUser);
		assertEquals(testUser, daoObject.get(testUser.getId()));
		daoObject.delete(testUser);
		assertEquals(null, daoObject.get(testUser.getId()));
		tr.commit();
	}
	@Test
	public void testUpdate(){
		Transaction tr = daoObject.getSession().getTransaction();
		tr.begin();
		daoObject.save(testUser);
		User userForUpdate = daoObject.get(testUser.getId());
		userForUpdate.setUsername("ivan doskovic");
		daoObject.update(userForUpdate);
		assertEquals(userForUpdate.getUsername(), daoObject.get(testUser.getId()).getUsername());
		assertEquals(userForUpdate, daoObject.get(testUser.getId()));
		tr.commit();
	}
	@Test
	public void testFindUser(){
		Transaction tr = daoObject.getSession().getTransaction();
		tr.begin();
		testUser.setUsername("ivan");
		testUser.setPassword("abcdef");
		daoObject.save(testUser);
		User wantedUser= daoObject.findUser("ivan", "abcdef");
		assertNotNull(wantedUser);
		tr.commit();
	}

}

@BeforeClass annotation annotate method which will be run before the first test method in the current class is invoked. In that method I set session to daoObject of UserDAOImpl class.

@BeforeMethod  annotate method which will be run before each test method. I want fresh instance of User class before each test method.

Each test method is in transaction scope. I do it manually (programmatic) creating transaction and at the end of method committing it.

Run testin.xml as TestNG suite. and you see tests results.

Results of tests using TestNG plugin in Eclipse

You will see data and test-output folders. Data folder is created by HSQL. There are 3 files. In testBase.properties file is stored properties for database which I’ve used for tests. Testbase.script file contains SQL for creating schema.  All data in tables are represented in testBase.log file in form of SQL query. All inserted data in database are automatically erased after all tests.

Folder structure after running tests

The annotated method will be run before each test method
Advertisements

From → Hibernate, Java

Leave a Comment

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

%d bloggers like this: