Announcement Announcement Module
Collapse
No announcement yet.
Configuring an in-memory datasource for unit tests Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Configuring an in-memory datasource for unit tests

    Hi,

    I'm trying to setup unit tests for my Spring service beans and I was suggested to write a special applicationContext.xml file to configure a testing database.
    The thing is that my application uses a HSQL data in in-process mode so at the moment when my tests are run, no database server instance is started up so with this bean declaration :
    Code:
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" destroy-method="close">
            <property name="driverClassName">
                <value>org.hsqldb.jdbcDriver</value>
            </property>
            <property name="url">
                <value>jdbc&#58;hsqldb&#58;hsql&#58;//127.0.0.1&#58;1701</value>
            </property>
            <property name="username">
                <value>sa</value>
            </property>
            <property name="password">
                <value></value>
            </property>
        </bean>
    My testing process throws an exception :
    Testcase: testHandleInitialize(ca.polymtl.larim.schaman.busi ness.SchamanImplTest): Caused an ERROR
    Could not create Hibernate transaction; nested exception is net.sf.hibernate.exception.GenericJDBCException: Cannot open connection
    org.springframework.transaction.CannotCreateTransa ctionException: Could not create Hibernate transaction; nested exception is net.sf.hibernate.exception.GenericJDBCException: Cannot open connection
    net.sf.hibernate.exception.GenericJDBCException: Cannot open connection
    at net.sf.hibernate.exception.ErrorCodeConverter.hand ledNonSpecificException(ErrorCodeConverter.java:90 )
    at net.sf.hibernate.exception.ErrorCodeConverter.conv ert(ErrorCodeConverter.java:79)
    at net.sf.hibernate.exception.JDBCExceptionHelper.con vert(JDBCExceptionHelper.java:29)
    at net.sf.hibernate.impl.BatcherImpl.convert(BatcherI mpl.java:328)
    at net.sf.hibernate.impl.BatcherImpl.openConnection(B atcherImpl.java:295)
    at net.sf.hibernate.impl.SessionImpl.connect(SessionI mpl.java:3373)
    at net.sf.hibernate.impl.SessionImpl.connection(Sessi onImpl.java:3333)
    at org.springframework.orm.hibernate.HibernateTransac tionManager.doBegin(HibernateTransactionManager.ja va:388)
    at org.springframework.transaction.support.AbstractPl atformTransactionManager.getTransaction(AbstractPl atformTransactionManager.java:289)
    at org.springframework.transaction.interceptor.Transa ctionAspectSupport.createTransactionIfNecessary(Tr ansactionAspectSupport.java:202)
    at org.springframework.transaction.interceptor.Transa ctionInterceptor.invoke(TransactionInterceptor.jav a:49)
    at org.springframework.aop.framework.ReflectiveMethod Invocation.proceed(ReflectiveMethodInvocation.java :144)
    at org.springframework.aop.framework.JdkDynamicAopPro xy.invoke(JdkDynamicAopProxy.java:174)
    at $Proxy5.initialize(Unknown Source)
    at ca.polymtl.larim.schaman.business.SchamanImplTest. testHandleInitialize(SchamanImplTest.java:31)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Nativ e Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Native MethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(De legatingMethodAccessorImpl.java:25)
    at org.apache.commons.jelly.tags.ant.AntTag.doTag(Ant Tag.java:185)
    at org.apache.commons.jelly.impl.TagScript.run(TagScr ipt.java:279)
    at org.apache.commons.jelly.impl.ScriptBlock.run(Scri ptBlock.java:135)
    at org.apache.commons.jelly.TagSupport.invokeBody(Tag Support.java:233)
    at org.apache.commons.jelly.tags.core.IfTag.doTag(IfT ag.java:88)
    at org.apache.commons.jelly.impl.TagScript.run(TagScr ipt.java:279)
    at org.apache.commons.jelly.impl.ScriptBlock.run(Scri ptBlock.java:135)
    at org.apache.maven.jelly.tags.werkz.MavenGoalTag.run BodyTag(MavenGoalTag.java:79)
    at org.apache.maven.jelly.tags.werkz.MavenGoalTag$Mav enGoalAction.performAction(MavenGoalTag.java:110)
    at com.werken.werkz.Goal.fire(Goal.java:639)
    at com.werken.werkz.Goal.attain(Goal.java:575)
    at com.werken.werkz.Goal.attainPrecursors(Goal.java:4 88)
    at com.werken.werkz.Goal.attain(Goal.java:573)
    at com.werken.werkz.Goal.attainPrecursors(Goal.java:4 88)
    at com.werken.werkz.Goal.attain(Goal.java:573)
    at com.werken.werkz.WerkzProject.attainGoal(WerkzProj ect.java:193)
    at org.apache.maven.jelly.tags.werkz.MavenAttainGoalT ag.doTag(MavenAttainGoalTag.java:127)
    at org.apache.commons.jelly.impl.TagScript.run(TagScr ipt.java:279)
    at org.apache.commons.jelly.impl.ScriptBlock.run(Scri ptBlock.java:135)
    at org.apache.maven.jelly.tags.werkz.MavenGoalTag.run BodyTag(MavenGoalTag.java:79)
    at org.apache.maven.jelly.tags.werkz.MavenGoalTag$Mav enGoalAction.performAction(MavenGoalTag.java:110)
    at com.werken.werkz.Goal.fire(Goal.java:639)
    at com.werken.werkz.Goal.attain(Goal.java:575)
    at org.apache.maven.plugin.PluginManager.attainGoals( PluginManager.java:671)
    at org.apache.maven.MavenSession.attainGoals(MavenSes sion.java:263)
    at org.apache.maven.cli.App.doMain(App.java:488)
    at org.apache.maven.cli.App.main(App.java:1239)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Nativ e Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Native MethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(De legatingMethodAccessorImpl.java:25)
    at com.werken.forehead.Forehead.run(Forehead.java:551 )
    at com.werken.forehead.Forehead.main(Forehead.java:58 1)
    Caused by: java.sql.SQLException: socket creation error
    at org.hsqldb.jdbc.jdbcUtil.sqlException(Unknown Source)
    at org.hsqldb.jdbc.jdbcConnection.<init>(Unknown Source)
    at org.hsqldb.jdbcDriver.getConnection(Unknown Source)
    at org.hsqldb.jdbcDriver.connect(Unknown Source)
    at java.sql.DriverManager.getConnection(DriverManager .java:512)
    at java.sql.DriverManager.getConnection(DriverManager .java:171)
    at org.springframework.jdbc.datasource.DriverManagerD ataSource.getConnectionFromDriverManager(DriverMan agerDataSource.java:156)
    at org.springframework.jdbc.datasource.DriverManagerD ataSource.getConnectionFromDriverManager(DriverMan agerDataSource.java:144)
    at org.springframework.jdbc.datasource.DriverManagerD ataSource.getConnection(DriverManagerDataSource.ja va:132)
    at org.springframework.orm.hibernate.LocalDataSourceC onnectionProvider.getConnection(LocalDataSourceCon nectionProvider.java:75)
    at net.sf.hibernate.impl.BatcherImpl.openConnection(B atcherImpl.java:292)
    ... 60 more
    So obviously I'm missing something in my bean configuration.
    I'm aware it's rather a question for Hibernate people but as this testing concern is very popular in Spring community, I thought I was more likely to get an answer to my problem here.

    FYI I'm using Spring 1.1.5 over Hibernate 2.1.8 and HSQLDB 1.7.3.3.

    Thx in advance

  • #2
    You'll need a URL like 'jdbc:hsqldb:file://C:/database/myHSQLDBInstance'

    Comment


    • #3
      Yes I thought of that since that's what I'm using inside my application but I would prefer something in memory rather than in a file if it's possible. Otherwise I'll use that thank you.

      Comment


      • #4
        I´m using this configuration for my unit tests:

        <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName"><value>org.hsqldb.jdbcDrive r</value> </property>
        <property name="url"><value>jdbc:hsqldb:mem:testdb</value></property>
        <property name="username"><value>sa</value></property>
        <property name="password"><value></value></property>
        <property name="defaultAutoCommit"><value>false</value></property>
        </bean>

        No local file is needed. Combined with hibernate´s auto-schema-update feature this is perfect :-)

        Best regards,

        Roman

        Comment


        • #5
          Thank you very much roman it's exactly what I needed. I'll try that tomorrow.
          Just one precision : is there something to configure somewhere to activate the Hibernate auto-schema-update feature of is it activated by default ?

          [edit]
          Besides, it's exactly why I preferred something in memory and not in a file. Because stop me if I'm wrong but in order to use the in-process mode (with a file) I first have to generate my database shema using schema export which is quite a heavy step to integrate in the testing process.
          [/edit]

          Comment


          • #6
            Actually there has to be something to configure with Hibernate because I've just tested your configuration (Yes I said tomorrow but I couldn't wait for this occasion to solve this issue I've been struggling with for more than a week ) and it throws the following exception :

            Testcase: testHandleInitialize(ca.polymtl.larim.schaman.busi ness.SchamanImplTest): Caused an ERROR
            Error performing 'ca.polymtl.larim.schaman.business.Schaman.initial ize(java.lang.String repositoryName, java.lang.String repositoryUri, java.lang.String adminEmail, java.lang.String adminName, java.lang.String adminPassword)' --> org.springframework.jdbc.BadSqlGrammarException: Bad SQL grammar [] in task 'Hibernate operation'; nested exception is java.sql.SQLException: Table not found: REPOSITORY in statement [insert into REPOSITORY (URI, NAME, ADMIN_NAME, ID) values (?, ?, ?, null)]
            ca.polymtl.larim.schaman.business.SchamanException : Error performing 'ca.polymtl.larim.schaman.business.Schaman.initial ize(java.lang.String repositoryName, java.lang.String repositoryUri, java.lang.String adminEmail, java.lang.String adminName, java.lang.String adminPassword)' --> org.springframework.jdbc.BadSqlGrammarException: Bad SQL grammar [] in task 'Hibernate operation'; nested exception is java.sql.SQLException: Table not found: REPOSITORY in statement [insert into REPOSITORY (URI, NAME, ADMIN_NAME, ID) values (?, ?, ?, null)]
            at ca.polymtl.larim.schaman.business.SchamanBase.init ialize(SchamanBase.java:146)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Nativ e Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(Native MethodAccessorImpl.java:39)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(De legatingMethodAccessorImpl.java:25)
            at org.springframework.aop.support.AopUtils.invokeJoi npointUsingReflection(AopUtils.java:284)
            at org.springframework.aop.framework.ReflectiveMethod Invocation.invokeJoinpoint(ReflectiveMethodInvocat ion.java:155)
            at org.springframework.aop.framework.ReflectiveMethod Invocation.proceed(ReflectiveMethodInvocation.java :122)
            at org.springframework.orm.hibernate.HibernateInterce ptor.invoke(HibernateInterceptor.java:163)
            at org.springframework.aop.framework.ReflectiveMethod Invocation.proceed(ReflectiveMethodInvocation.java :144)
            at org.springframework.transaction.interceptor.Transa ctionInterceptor.invoke(TransactionInterceptor.jav a:56)
            at org.springframework.aop.framework.ReflectiveMethod Invocation.proceed(ReflectiveMethodInvocation.java :144)
            at org.springframework.aop.framework.JdkDynamicAopPro xy.invoke(JdkDynamicAopProxy.java:174)
            at $Proxy5.initialize(Unknown Source)
            at ca.polymtl.larim.schaman.business.SchamanImplTest. testHandleInitialize(SchamanImplTest.java:31)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Nativ e Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(Native MethodAccessorImpl.java:39)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(De legatingMethodAccessorImpl.java:25)
            at org.apache.commons.jelly.tags.ant.AntTag.doTag(Ant Tag.java:185)
            at org.apache.commons.jelly.impl.TagScript.run(TagScr ipt.java:279)
            at org.apache.commons.jelly.impl.ScriptBlock.run(Scri ptBlock.java:135)
            at org.apache.commons.jelly.TagSupport.invokeBody(Tag Support.java:233)
            at org.apache.commons.jelly.tags.core.IfTag.doTag(IfT ag.java:88)
            at org.apache.commons.jelly.impl.TagScript.run(TagScr ipt.java:279)
            at org.apache.commons.jelly.impl.ScriptBlock.run(Scri ptBlock.java:135)
            at org.apache.maven.jelly.tags.werkz.MavenGoalTag.run BodyTag(MavenGoalTag.java:79)
            at org.apache.maven.jelly.tags.werkz.MavenGoalTag$Mav enGoalAction.performAction(MavenGoalTag.java:110)
            at com.werken.werkz.Goal.fire(Goal.java:639)
            at com.werken.werkz.Goal.attain(Goal.java:575)
            at com.werken.werkz.Goal.attainPrecursors(Goal.java:4 88)
            at com.werken.werkz.Goal.attain(Goal.java:573)
            at com.werken.werkz.Goal.attainPrecursors(Goal.java:4 88)
            at com.werken.werkz.Goal.attain(Goal.java:573)
            at com.werken.werkz.WerkzProject.attainGoal(WerkzProj ect.java:193)
            Indicating that it didn't find one of my tables...

            Any idea ?

            Comment


            • #7
              in order to use the in-process mode (with a file) I first have to generate my database shema using schema export which is quite a heavy step to integrate in the testing process
              You usually don't do this often, and at most once before a test run.

              is there something to configure somewhere to activate the Hibernate auto-schema-update feature of is it activated by default ?
              Haven't tried it, but it should be something like:
              Code:
              <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
              	<property name="dataSource"><ref local="dataSource"/></property>
              	<property name="configLocation"><value>classpath&#58;hibernate.cfg.xml</value></property> 
              	<property name="schemaUpdate"><value>true</value></property> 
              </bean>

              Comment


              • #8
                Originally posted by katentim
                You usually don't do this often, and at most once before a test run.
                Actually for me it happens quite often because I'm using AndroMDA to generate the basic structure of my code so I'm working in a short-iteration fashion which forces me to regenerate my database schema every time I update my UML model.

                is there something to configure somewhere to activate the Hibernate auto-schema-update feature of is it activated by default ?
                Haven't tried it, but it should be something like:
                Code:
                <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
                	<property name="dataSource"><ref local="dataSource"/></property>
                	<property name="configLocation"><value>classpath&#58;hibernate.cfg.xml</value></property> 
                	<property name="schemaUpdate"><value>true</value></property> 
                </bean>
                I'll try that, thank you.

                Comment


                • #9
                  Haven't tried it, but it should be something like
                  Just tried then...works well

                  Comment


                  • #10
                    Actually I couldn't modify my sessionFactory bean declaration because it's generated automatically by AndroMDA. But I tried something else and it seems I made progress but it's not solved yet.
                    In fact to activate schema auto update I added some hibernate.properties file on my test classpath with the following single line inside :
                    Code:
                    hibernate.hbm2ddl.auto=update
                    And now it seems to work with my database since the first accesses don't throw any exception until I try to access some Collection and then I get a "lazy loading exception".
                    Code:
                    Testcase&#58; testHandleInitialize&#40;ca.polymtl.larim.schaman.business.SchamanImplTest&#41;&#58;	Caused an ERROR
                    Failed to lazily initialize a collection - no session or session was closed
                    net.sf.hibernate.LazyInitializationException&#58; Failed to lazily initialize a collection - no session or session was closed
                    	at net.sf.hibernate.collection.PersistentCollection.initialize&#40;PersistentCollection.java&#58;209&#41;
                    	at net.sf.hibernate.collection.PersistentCollection.read&#40;PersistentCollection.java&#58;71&#41;
                    	at net.sf.hibernate.collection.Set.size&#40;Set.java&#58;106&#41;
                    	at ca.polymtl.larim.schaman.business.SchamanImplTest.testHandleInitialize&#40;SchamanImplTest.java&#58;33&#41;
                    	at sun.reflect.NativeMethodAccessorImpl.invoke0&#40;Native Method&#41;
                    	at sun.reflect.NativeMethodAccessorImpl.invoke&#40;NativeMethodAccessorImpl.java&#58;39&#41;
                    	at sun.reflect.DelegatingMethodAccessorImpl.invoke&#40;DelegatingMethodAccessorImpl.java&#58;25&#41;
                    	at org.apache.commons.jelly.tags.ant.AntTag.doTag&#40;AntTag.java&#58;185&#41;
                    	at org.apache.commons.jelly.impl.TagScript.run&#40;TagScript.java&#58;279&#41;
                    	at org.apache.commons.jelly.impl.ScriptBlock.run&#40;ScriptBlock.java&#58;135&#41;
                    	at org.apache.commons.jelly.TagSupport.invokeBody&#40;TagSupport.java&#58;233&#41;
                    	at org.apache.commons.jelly.tags.core.IfTag.doTag&#40;IfTag.java&#58;88&#41;
                    	at org.apache.commons.jelly.impl.TagScript.run&#40;TagScript.java&#58;279&#41;
                    	at org.apache.commons.jelly.impl.ScriptBlock.run&#40;ScriptBlock.java&#58;135&#41;
                    	at org.apache.maven.jelly.tags.werkz.MavenGoalTag.runBodyTag&#40;MavenGoalTag.java&#58;79&#41;
                    	at org.apache.maven.jelly.tags.werkz.MavenGoalTag$MavenGoalAction.performAction&#40;MavenGoalTag.java&#58;110&#41;
                    	at com.werken.werkz.Goal.fire&#40;Goal.java&#58;639&#41;
                    	at com.werken.werkz.Goal.attain&#40;Goal.java&#58;575&#41;
                    	at com.werken.werkz.Goal.attainPrecursors&#40;Goal.java&#58;488&#41;
                    	at com.werken.werkz.Goal.attain&#40;Goal.java&#58;573&#41;
                    	at com.werken.werkz.Goal.attainPrecursors&#40;Goal.java&#58;488&#41;
                    	at com.werken.werkz.Goal.attain&#40;Goal.java&#58;573&#41;
                    	at com.werken.werkz.WerkzProject.attainGoal&#40;WerkzProject.java&#58;193&#41;
                    	at org.apache.maven.jelly.tags.werkz.MavenAttainGoalTag.doTag&#40;MavenAttainGoalTag.java&#58;127&#41;
                    	at org.apache.commons.jelly.impl.TagScript.run&#40;TagScript.java&#58;279&#41;
                    	at org.apache.commons.jelly.impl.ScriptBlock.run&#40;ScriptBlock.java&#58;135&#41;
                    	at org.apache.maven.jelly.tags.werkz.MavenGoalTag.runBodyTag&#40;MavenGoalTag.java&#58;79&#41;
                    	at org.apache.maven.jelly.tags.werkz.MavenGoalTag$MavenGoalAction.performAction&#40;MavenGoalTag.java&#58;110&#41;
                    	at com.werken.werkz.Goal.fire&#40;Goal.java&#58;639&#41;
                    	at com.werken.werkz.Goal.attain&#40;Goal.java&#58;575&#41;
                    	at org.apache.maven.plugin.PluginManager.attainGoals&#40;PluginManager.java&#58;671&#41;
                    	at org.apache.maven.MavenSession.attainGoals&#40;MavenSession.java&#58;263&#41;
                    	at org.apache.maven.cli.App.doMain&#40;App.java&#58;488&#41;
                    	at org.apache.maven.cli.App.main&#40;App.java&#58;1239&#41;
                    	at sun.reflect.NativeMethodAccessorImpl.invoke0&#40;Native Method&#41;
                    	at sun.reflect.NativeMethodAccessorImpl.invoke&#40;NativeMethodAccessorImpl.java&#58;39&#41;
                    	at sun.reflect.DelegatingMethodAccessorImpl.invoke&#40;DelegatingMethodAccessorImpl.java&#58;25&#41;
                    	at com.werken.forehead.Forehead.run&#40;Forehead.java&#58;551&#41;
                    	at com.werken.forehead.Forehead.main&#40;Forehead.java&#58;581&#41;
                    I know about that exception, I already experienced it in my application and as it is a web application I configured an OpenSessionInViewFilter to solve it but there, in my test environment I don't understand where the session is opened and closed so I don't know how to solve it.
                    Is there a way, a property for example, something I could add to my hibernate.properties file in order to deactivate lazy loading completely for tests and get rid of this exception ?

                    Thx in advance.

                    Comment


                    • #11
                      Is there a way, a property for example, something I could add to my hibernate.properties file in order to deactivate lazy loading completely for tests and get rid of this exception ?
                      That would probably remove some value from your tests. You'd be better off simulating the open session filter.

                      Having said that, you can set lazy="false" in your mapping files. Another option is to use an outer join to force the load (or does AndroMDA prevent you from doing this) - again this is something you could use in production, but wouldn't really want to change just for a test.

                      Comment


                      • #12
                        The only thing I can control completely is the datasource bean configuration because it's in a separated file. You may think of AndroMDA as a constraining tool if you don't know it but believe me : it's amazing the time you save with it. There is just this small configuration detail I have to figure out in order to be able to test my one configuration file.

                        Roman if you can read me, since you provided me with this in-memory configuration, have you ever experienced that kind of lazy loading exception and found a solution ? Anyone? Is there another way for me to test my services simply without having to write the whole Spring configuration file by hand ?

                        Pleaaaase help...

                        Comment


                        • #13
                          Is there another way for me to test my services simply without having to write the whole Spring configuration file by hand ?
                          Take a look at AbstractTransactionalSpringContextTests

                          Comment

                          Working...
                          X