Over a million developers have joined DZone.

Using Groovy & BeanBuilder for Spring + Hibernate Integration Testing

DZone's Guide to

Using Groovy & BeanBuilder for Spring + Hibernate Integration Testing

· Database Zone
Free Resource

Whether you work in SQL Server Management Studio or Visual Studio, Redgate tools integrate with your existing infrastructure, enabling you to align DevOps for your applications with DevOps for your SQL Server databases. Discover true Database DevOps, brought to you in partnership with Redgate.

It is already pretty widely known how great Groovy is for writing unit tests for your Java code. Thanks to having first class constructs for lists, maps and ranges combined with built in support for mocking using Groovy for your unit testing is a great way to introduce Groovy into a Java codebase.

However, integration testing is a different kettle of fish and, in the case of Spring+Hibernate, often involves a combination of in-memory databases, Spring containers and so on. The traditional way to perform integration testing in Spring is to extend something like AbstractDependencyInjectionSpringContextTests and then override the getConfigLocations method to supply a static Spring XML configuration to use. For example here is a snippet from one of Grails' tests that uses this technique:

     protected String[] getConfigLocations() {
return new String[] { "org/codehaus/groovy/grails/orm/hibernate/hibernate-mapped-class-tests.xml" };


The Spring XML would do the job of setting up any singleton beans that your classes depend on such as a LocalSessionFactoryBean for Hibernate, the in-memory DataSource using something like HSQLDB and so on. However, all of this is rather tedious as you then have to maintain a separate XML file from your test and, worse, make sure its on the classpath in your build and in your IDE when running the test. The result is rather painful.

The good news is with Grails' BeanBuilder there is a better way! For those of you who don't know BeanBuilder is a DSL for Spring that allows you to construct an ApplicationContext on the fly using a Groovy builder like syntax. We're going to use it to construct an ApplicationContext to use in an integration test involving Hibernate.

The first thing we need to do is create some Hibernate entities. Since we're already using Groovy we may as well write those in Groovy as the syntax is a little more terse:

package com.mycompany
import javax.persistence.*
import org.hibernate.annotations.*

class FaqSection
@GeneratedValue(strategy = javax.persistence.GenerationType.IDENTITY)
Long id

Long version

String title

@OneToMany(cascade = [javax.persistence.CascadeType.ALL], targetEntity = FaqElement.class)
@JoinColumn(name = "section_id", nullable = false)
@IndexColumn(name = "pos", base = 0)
List elements

class FaqElement
@GeneratedValue(strategy = javax.persistence.GenerationType.IDENTITY)
Long id

Long version

String question
String answer

@JoinColumn(name = "section_id", nullable = false, updatable = false, insertable = false)
FaqSection section


Besides the JPA annotations which are a bit of eyesore, the code itself is pretty concise and just defines 2 entities that have a bidrectional one-to-many association between each other using a List collection. Once that is done we can define the Hibernate mapping for these:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"


<!-- a SessionFactory instance listed as /jndi/name -->
<!-- mapping files -->
<mapping class="com.mycompany.FaqSection" />
<mapping class="com.mycompany.FaqElement" />


I've saved these in a file called faq-service-hiberate.cfg.xml which we can refer to later, of course if you were using proper JPA you would create a persistence.xml etc. In my case I'm using straight Hibernate. Now to the interesting bit. Assuming we have some kind of FAQService defined as an interface with an FAQServiceImpl class providing the implementation to configure and wire these all up in the setUp method of our test using BeanBuilder it is as simple as:

import grails.spring.BeanBuilder
import org.apache.commons.dbcp.BasicDataSource
import org.hibernate.cfg.AnnotationConfiguration
import org.hibernate.SessionFactory
import com.mycompany.FAQService
import com.mycompany.FAQServiceImpl


FAQService faqService

protected void setUp() {
def bb = new BeanBuilder()

bb.beans {
dataSource(BasicDataSource) {
url = "jdbc:hsqldb:mem:testDB"
driverClassName = "org.hsqldb.jdbcDriver"
username = "sa"
password = ""
sessionFactory(LocalSessionFactoryBean) {
dataSource = dataSource
configLocation = "classpath:com/mycompany/test/faq-service-hiberate.cfg.xml"
configurationClass = AnnotationConfiguration
hibernateProperties = ["hibernate.hbm2ddl.auto":"create-drop"]
faqService(FAQServiceImpl) {
sessionFactory = sessionFactory

def ctx = bb.createApplicationContext()

faqService = ctx.getBean("faqService")

So that's pretty neat, whats going on here is I'm dynamically creating 3 beans: the dataSource, sessionFactory and faqService beans. These all get wired together with Spring and I can obtain a reference to the beans using the getBean method of the ApplicationContext.

So how could this be improved? The next step would be to write an abstract base class that constructed the ApplicationContext and then wired the beans into properties of the TestCase, so you could do something like:


class FaqServiceTests extends AbstractBeanBuilderDependencyInjectionTests {
def beans = {
// BeanBuilder code here

FAQSection faqSection

void testCreateFAQEntry() { }

Here it would read the "beans" property construct the ApplicationContext and wire the FAQSection bean into the test before calling the test method. But, I'll save an example of this for a future episode :-)

As for BeanBuilder itself, it is currently shipped as part of Grails, but can be used standalone by getting hold of the grails-spring-1.0.1.jar the latest version of which can be obtained here: http://dist.codehaus.org/grails


It’s easier than you think to extend DevOps practices to SQL Server with Redgate tools. Discover how to introduce true Database DevOps, brought to you in partnership with Redgate


Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}