views:

1374

answers:

3

Hi guys,

I'm working on trying to implement a JUnit test to check the functionality of a DAO. (The DAO will create/read a basic object/table relationship).

The trouble I'm having is the persistence of the DAO (for the non-test code) is being completed through an in-house solution using Spring/Hibernate, which eliminates the usual *.hbm.xml templates that most examples I have found contain.

Beacuse of this, I'm having some trouble understanding how to setup a JUnit test to implement the DAO to create/read (just very basic funtionality) to an in-memory HSQLDB. I have found a few examples, but the usage of the in-house persistence means I can't extend some of the classes the examples show (I can't seem to get the application-context.xml setup properly).

Can anyone suggest any projects/examples I could take a look at (or any documentation) to further my understanding of the best way to implement this test functionality? I feel like this should be really simple, but I keep running into problems implementing the examples I have found.

Thanks in advance!

edit:

Here's my solution for better readability, for anyone who needs a hand getting things going:

My Class:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContextTest-Example.xml")
@Transactional
public class ExampleDaoTest extends AbstractTransactionalJUnit4SpringContextTests {
@Resource(name = "sessionFactory")
private SessionFactory exampleSessionFactory;

@Resource(name = "exampleDao")
private ExampleDao exampleDao;

My applicationContext file:

<!-- List of Daos to be tested -->
<bean id="exampleDao" class="org.myExample.ExampleDao"/>

<!-- Datasource -->
<bean id="example_dataSource"
      class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="org.hsqldb.jdbcDriver">
    </property>
    <property name="url" value="jdbc:hsqldb:mem:ExampleTest">
    </property>
    <property name="username" value="sa">
    </property>
    <property name="password" value="">
    </property>
</bean>

<!-- Session Factory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="dataSource" ref="example_dataSource"/>
    <property name="annotatedClasses">
        <list>
            <value>org.myExample.ExampleClass</value>
        </list>
    </property>
    <property name="hibernateProperties">
        .... left to user to choose properties
    </property>
</bean>
+1  A: 

The bottom line with hibernate is the SessionFactory - your in-house solution will most likely be creating one of these somehow. Find out how, and then add a bean to create one in your test app context in the same way (or if possible using your in-house code that is used at runtime.). You may need to create your own FactoryBean to do the instantiation. (Use AbstractFactoryBean as your base class.)

Once this is in place, most of the examples using LocalSessionFactoryBean can be migrated to your situation - instead of using LocalsessionFactoryBean, use your custom factory bean.

(If you've not done so already, look at the Testing section in the spring reference - it makes testing with Spring, and injecting tests with beans from the context a breeze.)

mdma
A: 

See here. It assumes maven2 as build tool, but you can easily use anything.

Bozho
@downvoter - was it because I linked to my blog?
Bozho
+1  A: 

Spring 3 offers a new jdbc namespace that includes support for embedded databases, including HSQLDB. So that takes care of that part.

I'm wondering what the "in-house solution" could be. You can use annotations (either JPA or Hibernate annotations) to ORM your domain objects, so why do you need an "in-house solution"? E.g.:

<bean id="sessionFactory"
    class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"
    p:dataSource-ref="dataSource"
    p:packagesToScan="myapp.model" />

As far as implementing a test goes, use Spring's TestContext Framework. A test can look like this (again I'm assuming Spring 3 below, though it should work in Spring 2.5 simply by changing @Inject to @Autowired):

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({
    "/beans-datasource-it.xml",
    "/beans-dao.xml",
    "/beans-service.xml",
    "/beans-web.xml" })
@Transactional
public class ContactControllerIT {
    @Inject private ContactController controller;

    ... setUp() and tearDown() ...

    @Test
    public void testGetContact() {
        String viewName = controller.getContact(request, 1L, model);

        ... assertions ...
    }
}

You'd put the embedded database inside beans-datasource-it.xml, for example. ('it' here stands for integration test, and the files are on the classpath.) The controller in this example lives in beans-web.xml, and will be autowired into the ContactController field.

That's just an outline of what to do but hopefully it's enough to get you started.

Willie Wheeler