views:

1184

answers:

3

I am writing web application and am wondering what the recommended way is to populate initial data. This is JPA/Hibernate and Spring application and is built by maven. Up to now I've used script wich populate database with initial data, started by hand.
Unit tests work with theirs own data, created in code before each test. My test classes extends org.springframework.test.jpa.AbstractJpaTests.
Finally I'd like to have a maven build which create database form entities (now I need to run application first time to create database, then run script) then populates initial/dictionary data and run unit and integration tests. This process should be fully automated to put this build in CI server (hudson), crating new database from scratch is also appreciate.


Additional requirement: Database agnostic solution will be most valuable.

EDIT: Best example of what I'm looking for is init closure in BootStrap.groovy.

+3  A: 

EDIT: Added a link to a blog post showing how to test Hibernate JPA with Spring and DbUnit.

[...] I'd like to have a maven build which create database from entities

There is a maven hibernate3 plugin with an hibernate3:hbm2ddl goal that might help. Coupled with the maven sql plugin, it should be possible to create this schema from the generated DDL.

[...] then populates initial/dictionary data

Again, the maven sql plugin could do the job here. Or maybe with DBUnit which is another elegant solution (see the maven dbunit plugin).

and run unit and integration tests.

Well, I'm not sure your unit tests should access the database but, for integrations tests, check DBUnit as I said. It's really a very nice tool that allows you to setup up the database in a known state, test tables for expected content after a test execution and put the database back in the initial state. See Testing JPA Hibernate with Spring & DbUnit for a nice example.

This process should be fully automated to put this build in CI server (hudson), crating new database from scratch is also appreciate.

I think this is feasible.

Pascal Thivent
I consider using Unitils for my unit test. I wondering if there are way to define initial data in script/xml file, read them to java and persit using JPA/Hibernate - in database agnostic manner.
cetnar
Check DBUnit, this is what you're looking for, except it's not based on JPA. DBunit and its API allows you to define initial and expected datas in xml/csv, to load them from unit tests, to perform assert on table content, to restore the database in the initial state. And there is integration between DBUnit and Unitils (see http://www.unitils.org/apidocs/org/unitils/dbunit/package-summary.html)
Pascal Thivent
A: 

I solved a problem nearly identical to yours by extending

org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests

Then I used the hibernate3-maven-plugin to populate the database (I used hsqldb) at test time:

      <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>hibernate3-maven-plugin</artifactId>
            <version>2.1</version>
            <configuration>
                <components>
                    <component>
                        <name>hbm2ddl</name>
                        <implementation>jpaconfiguration</implementation>
                    </component>
                </components>
                <componentProperties>
                    <drop>true</drop>
                    <jdk5>true</jdk5>
                    <propertyfile>target/classes/jdbc.properties</propertyfile>
                    <skip>${maven.test.skip}</skip>
                </componentProperties>
            </configuration>
            <executions>
                <execution>
                    <phase>process-test-resources</phase>
                    <goals>
                        <goal>hbm2ddl</goal>
                    </goals>
                </execution>
            </executions>
            <dependencies>
                <dependency>
                    <groupId>${jdbc.groupId}</groupId>
                    <artifactId>${jdbc.artifactId}</artifactId>
                    <version>${jdbc.version}</version>
                </dependency>
            </dependencies>
        </plugin>

I posted a simple maven project at Google Code to demonstrate the technique.

David Krisch
Why don't you use DbUnit?
Pascal Thivent
I don't have any technical reasons for not using DBUnit. I just haven't used it. I will take a look at it and update my sample project appropriately.To this point I have created test data in code. This is reasonable for a sample project, but when it comes to testing real world code a solution like DBUnit will be necessary. Thank you for your suggestion.
David Krisch
+1  A: 

@David, thanks for your post. The only reasonable solution I've find to seed initial data is similar to yours - that is inserting data in tests. In my code I even don't use hibernate3-maven-plugin. Database creation in done by Spring in file jpaContext.xml

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="jpaVendorAdapter">
  <bean
    class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
      <property name="showSql" value="true" />
      <property name="generateDdl" value="true" />
      <property name="databasePlatform" value="org.hibernate.dialect.HSQLDialect"/>
  </bean>
</property>
<property name="dataSource" ref="dataSource"/>

As I wrote I use org.springframework.test.jpa.AbstractJpaTests with overriden method


  @Override
  protected String[] getConfigLocations() {
    return new String[]{
      "classpath:/jpaContext.xml"};
  }

I think it shold simplify your solution. I still search for a better resolution for creating initial data. Creating objects with a lot of relations by hand is cumbersome.

cetnar
Any negative feedback on DbUnit (just wondering if you are reading my answers and/or comments)?
Pascal Thivent
@Pascal. Why negative? :) I read your comments/answers. Most prefarable resolution for me is tunning (I'm still searching how) JPA/Hibernate way. Unitils/DBUnit is another good option but the second one.
cetnar