6

I have a collection of integration tests that have been generated by Spring Roo for my domain objects (and DAO ITDs).

They appear to be fixed to use the "production" applicationContext.xml, which reads the database.properties and connects to the MySQL database schema I have set up for experimenting with the project:

privileged aspect AdvertIntegrationTest_Roo_IntegrationTest {

    declare @type: AdvertIntegrationTest: @RunWith
        (SpringJUnit4ClassRunner.class);    

    declare @type: AdvertIntegrationTest: @ContextConfiguration
        (locations = "classpath:/META-INF/spring/applicationContext.xml");   

The outcome of this is that my demo database is frequently populated with garbage by these tests.

I'd like to change the configuration so that the integration tests use an in-mem database, and leave the MySQL database well alone. At the moment, the only option that I can see is to remove the Roo annotations and manage these tests myself from now on, but I'd rather keep Roo in the loop at the moment.

Is it possible to configure my project, so the "mvn tomcat" and "mvn test" commands use separate databases, without breaking the Spring Roo set-up? Or perhaps there is a better approach for what I want to do?

seanhodges
  • 17,426
  • 15
  • 71
  • 93
  • Update: I got some help from Ben Alex on the spring forums (http://forum.springsource.org/showthread.php?p=284703#post284703), it appears that Spring Roo does not yet provide any built-in support for this... – seanhodges Feb 18 '10 at 13:45

3 Answers3

6

Sean,

I have struggled with the same thing. I ended up putting a copy of applicationContext.xml in test/resources/META-INF/spring and modifying the line below:

<context:property-placeholder location="classpath*:META-INF/spring/test/*.properties"/>

In that 'test' directory the property place holder points to, i have put another database.properties which configures hsqldb.

Finally, I had to have a different copy of persistence.xml which configures the SQL Dialect (also in applicationContext.xml)

<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
    <property name="persistenceXmlLocation" value="classpath:META-INF/persistence-for-tests.xml"/>
    <property name="dataSource" ref="dataSource"/>
</bean>

I suppose that a more elegant solution through use of pom.xml magic is possible, but for now this seemed like an acceptable solution to me.

Hans

Hans Westerbeek
  • 5,645
  • 3
  • 34
  • 35
  • This is very useful, thanks! how did you instruct the Roo tests to use the "test" applicationContext.xml? Did you modify the generated AJ files? – seanhodges Feb 20 '10 at 09:44
  • no i did not modify any aj files, this is not required and also not recommended since they are created/managed exclusively by roo. Roo defers test execution to maven. maven will simply pick up the configuration files that live in test/resources and thus are on the classpath. – Hans Westerbeek Feb 20 '10 at 17:12
  • Thanks! I was having a similar problem where roo was trying to delete a random row and running into a FK constraint with my test data. Instead of following the above exactly, I just made a separate schema in my db for roo to run against. Then I didn't need to have a 2nd persistence.xml. – samspot Nov 02 '11 at 20:25
1

Sean, all

I had the same problem and found one more thing which might be useful to all. In persistence.xml one can define multiple persistence-unit with different names like:

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <persistence xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
    http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">

    <!-- production persistence unit -->
    <persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL">
    ...
    </persistence-unit>
    <!-- test persistence unit -->
    <persistence-unit name="testPersistenceUnit" transaction-type="RESOURCE_LOCAL">
    ...
    </persistence-unit>
    </persistence>

Then in your applicationContext.xml (this one for tests )only 2 changes are needed:

  1. properties files are loaded form META-INF/spring-test/*

    <context:property-placeholder location="classpath*:META-INF/spring-test/*.properties"/>
    
  2. persistenceUnitName points to "testPersistenceUnit" in persistance.xml

    <bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
    <property name="persistenceUnitName" value="testPersistenceUnit"/>
    <property name="dataSource" ref="dataSource"/>
    

Hope this will help someone as there is many answers there but it is hard to find out that you can have multiple persistenceUnits defined in one persistence.xml

Szymon

szydan
  • 2,318
  • 1
  • 15
  • 16
0

For me these steps worked fine:

1) Add a new persistence unit in your src/main/resources/META-INF/persistence.xml for your test purpose:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
   <!-- Production Database -->
   <persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL">
      <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
      <properties>
         <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" />
         <!-- value="create" to build a new database on each run; value="update" to modify an existing database; value="create-drop" means the same as "create" but also drops tables when Hibernate closes; value="validate" makes no changes to the database -->
         <property name="hibernate.hbm2ddl.auto" value="update" />
         <property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy" />
         <property name="hibernate.connection.charSet" value="UTF-8" />
         <!-- Uncomment the following two properties for JBoss only -->
         <!-- property name="hibernate.validator.apply_to_ddl" value="false" /-->
         <!-- property name="hibernate.validator.autoregister_listeners" value="false" /-->
      </properties>
   </persistence-unit>

   <!-- Test Database -->
   <persistence-unit name="persistenceUnitTest" transaction-type="RESOURCE_LOCAL">
      <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
      <properties>
         <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" />
         <!-- value="create" to build a new database on each run; value="update" to modify an existing database; value="create-drop" means the same as "create" but also drops tables when Hibernate closes; value="validate" makes no changes to the database -->
         <property name="hibernate.hbm2ddl.auto" value="create" />
         <property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy" />
         <property name="hibernate.connection.charSet" value="UTF-8" />
         <!-- Uncomment the following two properties for JBoss only -->
         <!-- property name="hibernate.validator.apply_to_ddl" value="false" /-->
         <!-- property name="hibernate.validator.autoregister_listeners" value="false" /-->
      </properties>
   </persistence-unit>
</persistence>

2) Copy the files applicationContext.xml and database.properties from src/main/resources/META-INF/spring to src/test/resources/META-INF/spring (if this folder does not exist create it).

3) Replace the content of the src/test/resources/META-INF/spring/database.properties in something like this:

#Updated at Sat Sep 12 22:13:10 CEST 2015
#Sat Sep 12 22:13:10 CEST 2015
database.test.driverClassName=org.h2.Driver
database.test.url=jdbc:h2:./src/test/resources/db/data
database.test.username=sa
database.test.password=

4) Rename the file src/test/resources/META-INF/spring/applicationContext.xml from applicationContext.xml to testApplicationContext.xml and change its content in something like this (simply change database references in database.test and the persistenceUnitName property value from persistenceUnit to persistenceUnitTest)

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd         http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd         http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
    <context:property-placeholder location="classpath*:META-INF/spring/*.properties"/>
    <context:spring-configured/>
    <context:component-scan base-package="com.jitter.finance.analyzer">
        <context:exclude-filter expression=".*_Roo_.*" type="regex"/>
        <context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
    </context:component-scan>
    <bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" id="dataSource">
        <property name="driverClassName" value="${database.test.driverClassName}"/>
        <property name="url" value="${database.test.url}"/>
        <property name="username" value="${database.test.username}"/>
        <property name="password" value="${database.test.password}"/>
        <property name="testOnBorrow" value="true"/>
        <property name="testOnReturn" value="true"/>
        <property name="testWhileIdle" value="true"/>
        <property name="timeBetweenEvictionRunsMillis" value="1800000"/>
        <property name="numTestsPerEvictionRun" value="3"/>
        <property name="minEvictableIdleTimeMillis" value="1800000"/>
    </bean>
    <bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>
    <tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>
    <bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
        <property name="persistenceUnitName" value="persistenceUnitTest"/>
        <property name="dataSource" ref="dataSource"/>
    </bean>
</beans>

5) Finally you can test your class like this:

import org.junit.Test;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;

@ContextConfiguration(locations = {"classpath*:/META-INF/spring/testApplicationContext*.xml"})
public class QuoteListTest extends AbstractJUnit4SpringContextTests {
    @Test
    public void checkQuote(){
        /* some code to test, this will interact with the defined database.test */
    }
}
madx
  • 6,723
  • 4
  • 55
  • 59