-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 11 posts ] 
Author Message
 Post subject: Dao testing
PostPosted: Thu May 13, 2010 3:23 am 
Pro
Pro

Joined: Mon Apr 16, 2007 8:10 am
Posts: 246
Hello,

I'm trying to code a Dao class and its integration testing but I run into several issues.

Here is the Dao class:

Code:
public class PreferenceHibernateDao extends HibernateDaoSupport implements PreferenceDao {

   private static Logger logger = Logger.getLogger(PreferenceHibernateDao.class);

   private static final Class<Preference> PREFERENCE_CLASS = Preference.class;

   public Integer insert(Preference client) {
      return (Integer) getHibernateTemplate().save(client);
   }

   public void update(Preference client) {
      getHibernateTemplate().save(client);
   }

   public void delete(Preference client) {
      getHibernateTemplate().delete(client);
   }

   public List<Preference> selectAll() {
      List<Preference> preferences = getHibernateTemplate().loadAll(Preference.class);
      return preferences;
   }

   public Preference selectById(final Integer id) {
      Preference preference = null;
      preference = (Preference) getHibernateTemplate().load(PREFERENCE_CLASS, id);
      return (preference);
   }

   public List<Preference> selectByName(final String name) {
      DetachedCriteria criteria = DetachedCriteria.forClass(PREFERENCE_CLASS).add(Property.forName("name").eq(name));
      List<Preference> list = getHibernateTemplate().findByCriteria(criteria);
      return list;
   }

}


And here is the integration testing:

Code:
   
@Test
   public void testSave() {
      Preference preference = new Preference();
      preference.setName("A_UNIQUE_NAME");
      preference.setValue("VALUE");
      Integer preferenceId = preferenceDao.insert(preference);
      assertNotNull(preferenceId);
      preference.setName("A_UNIQUE_NEW_NAME");
      preferenceDao.update(preference);
      Preference loadedPreference = preferenceDao.selectById(preferenceId);
      assertNotNull(loadedPreference.getId());
      assertEquals(preference.getName(), loadedPreference.getName());
   }


The first issue is that, after the test is run, there is no record in the database with a name A_UNIQUE_NEW_NAME but there is one with the name A_UNIQUE_NAME. This means that the object was not updated.

The statement
preference.setName("A_UNIQUE_NEW_NAME");
preferenceDao.update(preference);
did not do its job.


Top
 Profile  
 
 Post subject: 2nd issue
PostPosted: Thu May 13, 2010 3:30 am 
Pro
Pro

Joined: Mon Apr 16, 2007 8:10 am
Posts: 246
I also tried to delete the record from the database by adding the statement
preferenceDao.delete(preference);
to the integration testing.

Here is how it looks with the added statement:

Code:
   @Test
   public void testSave() {
      Preference preference = new Preference();
      preference.setName("A_UNIQUE_NAME");
      preference.setValue("VALUE");
      Integer preferenceId = preferenceDao.insert(preference);
      assertNotNull(preferenceId);
      preference.setName("A_UNIQUE_NEW_NAME");
      preferenceDao.update(preference);
      Preference loadedPreference = preferenceDao.selectById(preferenceId);
      assertNotNull(loadedPreference.getId());
      assertEquals(preference.getName(), loadedPreference.getName());
      preferenceDao.delete(preference);
   }


But it did not delete the record from the database.

The record was still in the table with its original name.

So I tried to add another delete statement, a bit shooting in the dark, to have the test like:

Code:
   @Test
   public void testSave() {
      Preference preference = new Preference();
      preference.setName("A_UNIQUE_NAME");
      preference.setValue("VALUE");
      Integer preferenceId = preferenceDao.insert(preference);
      assertNotNull(preferenceId);
      preference.setName("A_UNIQUE_NEW_NAME");
      preferenceDao.update(preference);
      Preference loadedPreference = preferenceDao.selectById(preferenceId);
      assertNotNull(loadedPreference.getId());
      assertEquals(preference.getName(), loadedPreference.getName());
      preferenceDao.delete(preference);
      preferenceDao.delete(loadedPreference);
   }


But it did not help. The record was still in the database.


Top
 Profile  
 
 Post subject: Re: Dao testing
PostPosted: Thu May 13, 2010 3:32 am 
Pro
Pro

Joined: Mon Apr 16, 2007 8:10 am
Posts: 246
Note that I'm running the test against a MySQL database.

Normally I have my integration testing running against an in memory HSQLDB database, but in this case I'm running it against a MySQL database to see how the test behaves.


Top
 Profile  
 
 Post subject: 3rd issue
PostPosted: Thu May 13, 2010 3:38 am 
Pro
Pro

Joined: Mon Apr 16, 2007 8:10 am
Posts: 246
Now, I'm trying to retrieve the record from the table.

Remember that the record could not be deleted by the delete statements, and it thus still exists in the table.

So, I add to the integration test a selectById statement.

The test now looks like:

@Test
public void testSave() {
Preference preference = new Preference();
preference.setName("A_UNIQUE_NAME");
preference.setValue("VALUE");
Integer preferenceId = preferenceDao.insert(preference);
assertNotNull(preferenceId);
preference.setName("A_UNIQUE_NEW_NAME");
preferenceDao.update(preference);
Preference loadedPreference = preferenceDao.selectById(preferenceId);
assertNotNull(loadedPreference.getId());
assertEquals(preference.getName(), loadedPreference.getName());
preferenceDao.delete(preference);
loadedPreference = preferenceDao.selectById(preferenceId);
}

But when running the test I got a
org.hibernate.ObjectNotFoundException: No row with the given identifier exists

Here is the stack:

Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.043 sec <<< FAILURE!
testSave(com.thalasoft.learnintouch.core.dao.PreferenceDaoTest) Time elapsed: 0.038 sec <<< ERROR!
org.springframework.orm.hibernate3.HibernateObjectRetrievalFailureException: No row with the given identifier exists: [com.thalasoft.learnintouch.core.domain.Preference#114]; nested exception is org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [com.thalasoft.learnintouch.core.domain.Preference#114]
at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:660)
at org.springframework.orm.hibernate3.HibernateAccessor.convertHibernateAccessException(HibernateAccessor.java:412)
at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:424)
at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)
at org.springframework.orm.hibernate3.HibernateTemplate.load(HibernateTemplate.java:563)
at org.springframework.orm.hibernate3.HibernateTemplate.load(HibernateTemplate.java:557)
at com.thalasoft.learnintouch.core.dao.hibernate.PreferenceHibernateDao.selectById(PreferenceHibernateDao.java:40)


So I tried to catch the exception in the Dao class, by adding a catch block like:

Code:
   public Preference selectById(final Integer id) {
      Preference preference = null;
      try {
         preference = (Preference) getHibernateTemplate().load(PREFERENCE_CLASS, id);
      } catch (ObjectNotFoundException e) {         
      }
      return (preference);
   }


But when running the test, I still got a org.hibernate.ObjectNotFoundException: No row with the given identifier exists.

Here is the stack:

Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.052 sec <<< FAILURE!
testSave(com.thalasoft.learnintouch.core.dao.PreferenceDaoTest) Time elapsed: 0.047 sec <<< ERROR!
org.springframework.orm.hibernate3.HibernateObjectRetrievalFailureException: No row with the given identifier exists: [com.thalasoft.learnintouch.core.domain.Preference#113]; nested exception is org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [com.toto.core.domain.Preference#113]
at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:660)
at org.springframework.orm.hibernate3.HibernateAccessor.convertHibernateAccessException(HibernateAccessor.java:412)
at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:424)
at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)
at org.springframework.orm.hibernate3.HibernateTemplate.load(HibernateTemplate.java:563)
at org.springframework.orm.hibernate3.HibernateTemplate.load(HibernateTemplate.java:557)
at com.toto.core.dao.hibernate.PreferenceHibernateDao.selectById(PreferenceHibernateDao.java:40)

It's like the catch block did not catch the exception.


Top
 Profile  
 
 Post subject: Re: Dao testing
PostPosted: Thu May 13, 2010 3:53 am 
Pro
Pro

Joined: Mon Apr 16, 2007 8:10 am
Posts: 246
For info, here is the mapping:

Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated Apr 18, 2010 1:03:51 PM by Hibernate Tools 3.2.1.GA -->
<hibernate-mapping>
    <class name="com.thalasoft.learnintouch.core.domain.Preference" table="preference">
        <id name="id" type="java.lang.Integer">
            <column name="id" />
            <generator class="identity" />
        </id>
        <version name="version" type="int">
            <column name="version" not-null="true" />
        </version>
        <property name="name" type="string">
            <column name="name" length="50" not-null="true" unique="true" />
        </property>
        <property name="isMlText" type="string">
            <column name="is_ml_text" length="1" not-null="false" />
        </property>
        <property name="value" type="string">
            <column name="value" length="65535" not-null="false" />
        </property>
    </class>
</hibernate-mapping>


Top
 Profile  
 
 Post subject: Re: Dao testing
PostPosted: Thu May 13, 2010 10:24 am 
Pro
Pro

Joined: Mon Apr 16, 2007 8:10 am
Posts: 246
Or, do I need to have a flush() in each of the persisting methods of the Dao class ?

Like in the following:
Code:
   public Integer insert(Preference client) {
      Integer id = (Integer) getHibernateTemplate().save(client);
      getHibernateTemplate().flush();
      return id;
   }

   public void update(Preference client) {
      getHibernateTemplate().save(client);
      getHibernateTemplate().flush();
   }

   public void delete(Preference client) {
      getHibernateTemplate().delete(client);
      getHibernateTemplate().flush();
   }


Top
 Profile  
 
 Post subject: Re: Dao testing
PostPosted: Thu May 13, 2010 10:34 am 
Pro
Pro

Joined: Mon Apr 16, 2007 8:10 am
Posts: 246
Adding the statement

getHibernateTemplate().flush();

seems to have solved some issues here.

The only issue remaining here the one with the exception.

Here it is again:

No row with the given identifier exists: [com.thalasoft.learnintouch.core.domain.Preference#141]
at org.hibernate.impl.SessionFactoryImpl$1.handleEntityNotFound(SessionFactoryImpl.java:386)
at org.hibernate.proxy.AbstractLazyInitializer.checkTargetState(AbstractLazyInitializer.java:130)
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:119)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:150)
at org.hibernate.proxy.pojo.cglib.CGLIBLazyInitializer.invoke(CGLIBLazyInitializer.java:150)
at com.thalasoft.learnintouch.core.domain.Preference$$EnhancerByCGLIB$$e56184b0.toString(<generated>)
at java.lang.String.valueOf(String.java:2827)
at junit.framework.Assert.assertNull(Assert.java:225)
at com.thalasoft.learnintouch.core.dao.PreferenceDaoTest.testSave(PreferenceDaoTest.java:29)


Top
 Profile  
 
 Post subject: Re: Dao testing
PostPosted: Thu May 13, 2010 11:03 am 
Pro
Pro

Joined: Mon Apr 16, 2007 8:10 am
Posts: 246
The last exception was simply caused by the call

assertNull(loadedPreference);


Top
 Profile  
 
 Post subject: Re: Dao testing
PostPosted: Thu May 13, 2010 2:15 pm 
Pro
Pro

Joined: Mon Apr 16, 2007 8:10 am
Posts: 246
After reading all the blogs I could google, I understand I should not do a flush in the Dao methods like

getHibernateTemplate().flush();

So I remove that statement and my methods now look like:

Code:
   public Integer insert(Preference client) {
      Integer id = (Integer) getHibernateTemplate().save(client);
      return id;
   }

   public void update(Preference client) {
      getHibernateTemplate().saveOrUpdate(client);
   }

   public void delete(Preference client) {
      getHibernateTemplate().delete(client);
   }


But then, when running my integration test against the MySql database, I have some data left in the table after the test run is over.

Namely, I end up with an inserted, and not removed, record:

mysql> select * from preference where name like '%_UNIQUE_NAME';
+-----+---------+---------------+------------+-------+
| id | version | name | is_ml_text | value |
+-----+---------+---------------+------------+-------+
| 167 | 0 | A_UNIQUE_NAME | NULL | VALUE |
+-----+---------+---------------+------------+-------+

And this was not happening with the flush statements in place.

I thought Spring would provide me with some rolled back transaction feature so as to isolate my integration tests.

Where are the Hibernate gurus...


Top
 Profile  
 
 Post subject: Re: Dao testing
PostPosted: Thu May 13, 2010 7:41 pm 
Pro
Pro

Joined: Mon Apr 16, 2007 8:10 am
Posts: 246
I have now implemented a GenericDao that serves as a base class to the application Dao's but I still have the flush() calls...
Maybe my integration tests are not testing in a sensible way...


Top
 Profile  
 
 Post subject: Re: Dao testing
PostPosted: Thu May 13, 2010 7:54 pm 
Pro
Pro

Joined: Mon Apr 16, 2007 8:10 am
Posts: 246
I just ordered POJO in Action. It should help. Hopefully.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 11 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.