Chariot Training Classes

Training Courses

I run Chariot's training and mentoring services. We provide training in AngularJS, HTML5, Spring, Hibernate, Maven, Scala, and more.

Chariot Education Services

Technology

Chariot Emerging Tech

Learn about upcoming technologies and trends from my colleagues at Chariot Solutions.

Resources

Chariot Conferences

Podcasts

« SpringSource Roo - What is it? | Main | New Chariot TechCast posted on JSR-299 and WebBeans »
Tuesday
Jun022009

Gettin' all Testy - The Spring TestContext, Hibernate, and you...

I'm getting some materials ready around a project using the Hibernate Annotations API in Spring 2.5.6.  The client is using Hibernate rather than straight JPA, likely due to wanting to get features such as Filters, Criteria, etc...

I've been used to JUnit 3.x for a while, but as I'm testing my Hibernate knowledge, I came across the newer Spring Test Context framework.  If you install JUnit 4.4 (I'm using Maven, so I just added it as a test-time dependency) and also the spring test-context library, you'll have the ability to define tests that ramp up a Spring Context using the @ContextConfiguration annotation and coupled with extending a specific Spring abstract class, AbstractJUnit4SpringContextTests.

This is similar to the Junit 3.8 context configuration, but uses JUnit 4 semantics.  Also you can use TestNG, just use a different abstract class.  Here is a fragment:

@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public class HibernateModelTest 
   extends AbstractJUnit4SpringContextTests {
...
}

 

Ok, that's cool.  You get an applicationContext member in the test class too. So, what if you wanted to interact with the Hibernate API directly?  I've mounted my Hibernate configuration using the Spring Hibernate AnnotationSessionFactoryBean, scanning for entities in the org.rimple.example.domain package as in this example:

<bean id="mySessionFactory" class="org.springframework.orm.hibernate3.annotation.
AnnotationSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="packagesToScan" value="org.rimple.example.domain"/>
    <property name="hibernateProperties">
      <value>
        hibernate.dialect=org.hibernate.dialect.HSQLDialect
        hibernate.hbm2ddl.auto=create
        hibernate.cache.provider_class=org.hibernate.cache.NoCacheProvider
        hibernate.show_sql=true
        hibernate.current_session_context_class=thread
        hibernate.connection.pool_size=15
      </value>
    </property>
</bean>
       

Now I can just create a @Before and @After method to setup and tear down the session context.  I can get fancy and begin a transaction and end it, just like the transactional tests provided for Repository tests, but then I can open and close and interact with the session myself.

    private Session session;
    @Before
    public void setupSession() {
        SessionFactory sessionFactory = (SessionFactory) applicationContext.
getBean("mySessionFactory");
        session = sessionFactory.openSession();
        session.getTransaction().begin();
    }

    @After
    public void tearDownSession() {
        session.getTransaction().rollback();
        session.close();
    }

Now, all I have to do is just interact with Hibernate directly. Given this Entity:


@Entity
@Table(name="employees")
public class Employee {

    @Id @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;

    @Column(nullable=false, length=30)
    private String firstName;

    @Column(nullable=false, length=30)
    private String lastName;

    @Column(nullable=false)
    private Boolean active;

    @Column(nullable=false)
    @Temporal(TemporalType.DATE)
    private Date hireDate;

    @Column(nullable=true)
    private String comments;
    ...
}

We can use this test:

    @Test
    public void createEmployee() {
        Employee e = new Employee();
        e.setActive(true);
        e.setFirstName("Joe");
        e.setLastName("Smith");
        e.setComments("A new employee");
        e.setHireDate(new Date());

        session.save(e);
        assertNotNull(e);
    }

QED!  I am partial to the JPA Entity Manager and putting Hibernate behind a facade, but this works if your team decides they are using the Hibernate annotation and API instead.

PrintView Printer Friendly Version

EmailEmail Article to Friend

Reader Comments

There are no comments for this journal entry. To create a new comment, use the form below.

PostPost a New Comment

Enter your information below to add a new comment.

My response is on my own website »
Author Email (optional):
Author URL (optional):
Post:
 
Some HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>