Spring/Hibernate/Junit example of testing DAO against HSQLDB
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开发者_C百科 being completed through an in-house solution using Spring/Hibernate, which eliminates the usual *.hbm.xml
templates that most examples I have found contain.
Because of this, I'm having some trouble understanding how to setup a JUnit test to implement the DAO to create/read (just very basic functionality) 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.
edit:
Here's my solution for better readability, for anyone who needs a hand getting things going:
My
TestClass
:@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.xml
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 name="url" value="jdbc:hsqldb:mem:ExampleTest"/> <property name="username" value="sa"/> <property name="password" value=""/> </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>
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.
See here. It assumes maven2 as build tool, but you can easily use anything.
I have recently implemented a similar solution in some of my code using Hibernate, Spring and HSQLDB.
Its is worth noting that AbstractTransactionalJUnit4SpringContextTests
has now be deprecated - but it is still pretty straight forward to test - I cover most the details here: http://automateddeveloper.blogspot.com/2011/05/hibernate-spring-testing-dao-layer-with.html
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.)
My application context looks a bit different
<beans:bean class="org.apache.commons.dbcp.BasicDataSource" id="HSQL_DS">
<beans:property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
<beans:property name="url" value="jdbc:hsqldb:mem:Test"/>
<beans:property name="username" value="sa"/>
<beans:property name="password" value=""/>
</beans:bean>
<jdbc:embedded-database id="HSQL_DS">
<jdbc:script location="classpath:schema.sql"/>
<jdbc:script location="classpath:data.sql"/>
</jdbc:embedded-database>
and my test class looks like this:
public class Tester {
private EmbeddedDatabase db;
@Before
public void setUp(){
db = new EmbeddedDatabaseBuilder().addDefaultScripts().build();
}
@Test
public void TestMe(){
System.out.println("Testing");
}
@After
public void tearDown(){
db.shutdown();
}
}
精彩评论