Announcement Announcement Module
Collapse
No announcement yet.
AbstractTransactionalSpringContextTests to test CRUD ? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • AbstractTransactionalSpringContextTests to test CRUD ?

    I have a question about how to make AbstractTransactionalSpringContextTests to test DAO's CRUD methods...

    In my testing apps , I subclass JUnit's TestCase , setup BeanFactory , SessionFactory in setUp() , and I have another prepareData() before running a testCase , and cleanData() after the testCase.
    prepareData() is to insert some pre-defined data , for later testing. and cleanData() is to clean all data generated by prepareData() and during the test case.

    for example , to test DAO's Read , I may insert one row of data to table in prepareData() . Then , in testRead() , I assert it NotNull . Finally in cleanData() , I delete that data.

    I want to migrate these test cases to Spring's AbstractTransactionalSpringContextTests , but have no idea how to accomplish it.

    If I want to test C,R,U,D , should I subclass four classs from AbstractTransactionalSpringContextTests , and prepare data in each onSetUp() , and clean data in each onTearDown() ?

    Is that correct ??

  • #2
    and clean data in each onTearDown()
    The transaction will be rolled back by default (unless you call the setComplete() method in each test), so you don't need to clean DB data in the onTearDown.

    Comment


    • #3
      setDefaultRollback(false) will cause ObjectDeletedException

      Hi , I have an issue with HibernateObjectRetrievalFailureException when setDefaultRollback(false) ;

      Here is my scenario : There are two classes : Item and Series , which exists one-to-many relation.
      That is : one Item may belong to ZERO or ONE Series
      and one Series may have ZERO or MANY Items

      I wrote one DAO : ItemDao.
      I then wrote two test cases against ItemDao :

      1. testCreateItemWithoutDependency()
      Code:
      Creating new Item item1 ... with null Series
      Integer generatedId = (Integer) itemDao.create(item1);
      
      Item item2 = itemDao.getById(generatedId);
      assertEquals(item2, item1);
      itemDao.delete(item1);
      2. testCreateItemWithNewSeries()
      Code:
      Series series1 = new Series();
      Item item1 = new Item();
      item1.setSeries(series1);
      generatedId = (Integer) itemDao.create(item1);
      Item item2 = itemDao.getById(generatedId);
      assertEquals(item2, item1);
      assertEquals(item2.getSeries(), series1);
      //====== Clean Data ===========
      itemDao.delete(item1);
      If I setDefaultRollback(true) ; both tests passed.
      But if I setDefaultRollback(false) ; (because I want to see real data inserted to / deleted from Database) ; the second test failed with the following exception :

      Code:
      INFO  - Began transaction: transaction manager [[email protected]c4ad]; defaultRollback false
      ERROR - onTearDown error
      org.springframework.orm.hibernate3.HibernateObjectRetrievalFailureException: deleted object would be re-saved by cascade (remove deleted object from associations): [my.model.Item#3]; nested exception is org.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations): [my.model.Item#3]
      org.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations): [my.model.Item#3]
      	at org.hibernate.impl.SessionImpl.forceFlush(SessionImpl.java:742)
      	at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:166)
      	at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:96)
      	at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:69)
      	at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:468)
      	at org.hibernate.engine.Cascades$5.cascade(Cascades.java:154)
      	at org.hibernate.engine.Cascades.cascadeAssociation(Cascades.java:771)
      	at org.hibernate.engine.Cascades.cascade(Cascades.java:720)
      	at org.hibernate.engine.Cascades.cascadeCollection(Cascades.java:895)
      	at org.hibernate.engine.Cascades.cascadeAssociation(Cascades.java:792)
      	at org.hibernate.engine.Cascades.cascade(Cascades.java:720)
      	at org.hibernate.engine.Cascades.cascade(Cascades.java:847)
      	at org.hibernate.event.def.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:121)
      	at org.hibernate.event.def.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:112)
      	at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:59)
      	at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:26)
      	at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:730)
      	at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:324)
      	at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:86)
      	at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:490)
      	at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:495)
      	at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:468)
      	at org.springframework.test.AbstractTransactionalSpringContextTests.endTransaction(AbstractTransactionalSpringContextTests.java:206)
      	at org.springframework.test.AbstractTransactionalSpringContextTests.onTearDown(AbstractTransactionalSpringContextTests.java:152)
      	at org.springframework.test.AbstractDependencyInjectionSpringContextTests.tearDown(AbstractDependencyInjectionSpringContextTests.java:253)
      	at junit.framework.TestCase.runBare(TestCase.java:130)
      	at junit.framework.TestResult$1.protect(TestResult.java:106)
      	at junit.framework.TestResult.runProtected(TestResult.java:124)
      	at junit.framework.TestResult.run(TestResult.java:109)
      	at junit.framework.TestCase.run(TestCase.java:118)
      	at junit.framework.TestSuite.runTest(TestSuite.java:208)
      	at junit.framework.TestSuite.run(TestSuite.java:203)
      	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:478)
      	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:344)
      	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)

      I know this seems because both end of the association should be set correctly ,
      that is :
      item.getSeries().getItems().remove(this);
      item1.setSeries(null) ;
      But after adding the two line before itemDao.delete(item1) ; the exception still exists

      Can anybody tell me how to solve it ? Thanks in advenced.

      Comment


      • #4
        do you mean:

        Code:
        item.getSeries().getItems().remove(item1);
        item1.setSeries(null) ;
        Can you post your entire testCase.

        Also note that you *will* now get clashes between your individual test methods, i.e. if you try and create the same data in two different test methods you will get DuplicateData exceptions ....

        Comment


        • #5
          Thank you for replying so quickly . this is my full test case code :

          Code:
          package my.dao.hibernate.tests;
          
          import java.util.UUID;
          
          import org.springframework.jdbc.datasource.DriverManagerDataSource;
          
          import my.dao.ItemDao;
          import my.model.Item;
          import my.model.Series;
          
          public class ItemDaoTest extends AbstractSpringDaoTestCase
          {
            private ItemDao itemDao;
          
            public ItemDaoTest()
            {
              setDefaultRollback(false);
            }
          
            @Override
            protected void onSetUpInTransaction() throws Exception
            {
              super.onSetUpInTransaction();
              setDataSource((DriverManagerDataSource) applicationContext.getBean("dataSource"));
              itemDao = (ItemDao) this.applicationContext.getBean("itemDao");
            }
          
            @Override
            protected void onTearDownInTransaction()
            {
              itemDao = null;
            }
          
            public void testCreateItemWithoutDependency()
            {
              Item item1 = new Item();
              item1.setNumber("test" + UUID.randomUUID().toString().substring(0, 5));
          
              Integer generatedId = (Integer) itemDao.create(item1);
          
              Item item2 = itemDao.getById(generatedId);
              assertEquals(item2, item1);
          
              // ================ clean data ================
              itemDao.delete(item1);
            }
          
          
            public void testCreateItemWithNewSeries()
            {
              Series series1 = new Series();
              series1.setName("test" + UUID.randomUUID().toString().substring(0, 5));
          
              Item item1 = new Item();
              item1.setNumber("test" + UUID.randomUUID().toString().substring(0, 5));
              item1.setSeries(series1);
          
              Integer generatedId = (Integer) itemDao.create(item1);
              Item item2 = itemDao.getById(generatedId);
              assertEquals(item2, item1);
              assertEquals(item2.getSeries(), series1);
          
              // ================ clean data ================
              item1.getSeries().getItems().remove(item1);
              item1.setSeries(null);
              
              itemDao.delete(item1);
            }
          
          }
          And this is my AbstractSpringDaoTestCase.java :
          Code:
          package my.dao.hibernate.tests;
          
          import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests;
          
          public abstract class AbstractSpringDaoTestCase extends AbstractTransactionalDataSourceSpringContextTests
          {
            public AbstractSpringDaoTestCase()
            {
              setPopulateProtectedVariables(true);
            }
          
            @Override
            protected String[] getConfigLocations()
            {
              return new String[] { "xxx.xml" };
            }
          }
          In fact , in my Item.java , I also make setSeries(Series series) to a convenient method :
          Code:
            public void setSeries(Series series)
            {
              if (this.series != null && this.series.getItems().contains(this))
                this.series.getItems().remove(this);
              this.series = series;
              if (series != null)
                series.getItems().add(this);
            }
          Because of this method , in fact , I could only just call setSeries(null);
          But it also fails to the same Exception

          Comment


          • #6
            sorry , I've found the problem.
            It's because I make use of Database's id as my object's identity. (hashcode() , and equals() )

            After I use UUID as object's identity , it's all solved.

            Comment

            Working...
            X