Saturday, July 24, 2010

Unit Testing your JPA entities

If you want to avoid exceptions like this at runtime after adding properties to your JPA entities, it might be worthwhile to invest some time in writing unit tests for them.
Caused by: org.hibernate.MappingException: Could not determine type for: be.ecs.validation.entities.City, at table: Person, for columns: [org.hibernate.mapping.Column(city)]
at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:291)
at org.hibernate.tuple.PropertyFactory.buildStandardProperty(PropertyFactory.java:143)
at org.hibernate.tuple.component.ComponentMetamodel.(ComponentMetamodel.java:68)
at org.hibernate.mapping.Component.buildType(Component.java:183)
at org.hibernate.mapping.Component.getType(Component.java:176)
at org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:275)
at org.hibernate.mapping.Property.isValid(Property.java:217)
at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:464)
at org.hibernate.mapping.RootClass.validate(RootClass.java:236)
at org.hibernate.cfg.Configuration.validate(Configuration.java:1193)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1378)
at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:954)
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:891)
... 43 more

The Spring TestContext Framework provides generic, annotation-driven unit and integration testing support. More information can be found on http://static.springsource.org/spring/docs/3.0.3.RELEASE/spring-framework-reference/html/testing.html

The following needs to be done
  1. Create a persistence.xml specific to your unit tests
  2. Create a Spring application context to bootstrap the entitymanager
  3. Create the unit test that
  • constructs an entity
  • persists it
  • retrieves it
    1. Create a persistence.xml specific to your unit tests
    We'll create a dedicated persistence.xml file in our package (src/test/java/META-INF/persistence.xml). In this example, we're using an in-memory HSQL database.

    <persistence>
    <persistence-unit name="pu" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <class>be.ecs.validation.entities.Person</class>
    <class>be.ecs.validation.entities.City</class>
    <class>be.ecs.validation.entities.Country</class>
    <properties>
    <property name="hibernate.connection.url" value="jdbc:hsqldb:mem:unit-testing-jpa"/>
    <property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver"/>
    <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
    <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
    <property name="hibernate.connection.username" value="sa"/>
    <property name="hibernate.connection.password" value="x"/>
    <property name="hibernate.archive.autodetection" value="class, hbm"/>
    </properties>
    </persistence-unit>
    </persistence>



    2. Create a Spring application context

    xxx

    <beans>

    <bean id="entityManagerFactory"
    class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="pu" />
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>
    </beans>


    3. Create the unit test

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations={"/applicationContext.xml"})
    public class PersonPersistenceTest {

    @PersistenceContext
    private EntityManager entityManager;

    public EntityManager getEntityManager() {
    return entityManager;
    }

    @Test
    public void createAndPersistPerson() {
    Person person = new Person();
    getEntityManager().persist(person);
    Person retrievedPerson = getEntityManager().find(Person.class, person.getId());
    Assert.assertNotNull(retrievedPerson);
    }

    }

    1 comment:

    1. Great post! This is exactly what I'm looking for. It's absolutely relieving to know now just how to do a complicated unit testing with my JPA entities. Thanks!

      Piper Nunnery
      Mark from r├Ęgles anniversaire 

      ReplyDelete