Setup database for Unit tests with Spring, Hibernate and Spring Transaction Support
Posted
by
Michael Bulla
on Stack Overflow
See other posts from Stack Overflow
or by Michael Bulla
Published on 2012-06-10T16:38:37Z
Indexed on
2012/06/11
4:40 UTC
Read the original article
Hit count: 164
I want to test integration of dao-layer with my service-layer in a unit-test. So I need to setup some data in my database (hsql). For this setup I need an own transaction at the begining of my testcase to ensure that all my setup is really commited to database before starting my testcase.
So here's what I want to achieve:
// NotTranactional
public void doTest {
// transaction begins
setup database
// commit transaction
service.doStuff() // doStuff is annotated @Transactional(propagation=Propagation.REQUIRED)
}
Here is my not working code:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"/asynchUnit.xml"})
@DirtiesContext(classMode=ClassMode.AFTER_EACH_TEST_METHOD)
public class ReceiptServiceTest implements ApplicationContextAware {
@Autowired(required=true)
private UserHome userHome;
private ApplicationContext context;
@Before
@Transactional(propagation=Propagation.REQUIRED)
public void init() throws Exception {
User user = InitialCreator.createUser();
userHome.persist(user);
}
@Test
public void testDoSomething() {
...
}
}
Leading to this exception:
org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
at org.springframework.orm.hibernate3.SpringSessionContext.currentSession(SpringSessionContext.java:63)
at org.hibernate.impl.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:687)
at de.diandan.asynch.modell.GenericHome.getSession(GenericHome.java:40)
at de.diandan.asynch.modell.GenericHome.persist(GenericHome.java:53)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:318)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:196)
at $Proxy28.persist(Unknown Source)
at de.diandan.asynch.service.ReceiptServiceTest.init(ReceiptServiceTest.java:63)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:27)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
I dont know whats the right way to get the transaction around setup database.
What I tried:
@Before
@Transactional(propagation=Propagation.REQUIRED)
public void setup() {
setup database
}
-> Spring seems not to start transaction in @Before-annotated methods. Beyond that, thats not what I really want, cause there are a lot merhods in my testclass which needs a slightly differnt setup, so I need several of that init-methods.
@Transactional(propagation=Propagation.REQUIRED)
public void setup() {
setup database
}
public void doTest {
init();
service.doStuff() // doStuff is annotated @Transactional(propagation=Propagation.REQUIRED)
}
--> init seems not to get started in transaction
What I dont want to do:
public void doTest {
// doing my own transaction-handling
setup database
// doing my own transaction-handling
service.doStuff() // doStuff is annotated @Transactional(propagation=Propagation.REQUIRED)
}
--> start mixing springs transaction-handling and my own seems to get pain in the ass.
@Transactional(propagation=Propagation.REQUIRED)
public void doTest {
setup database
service.doStuff()
}
--> I want to test as real as possible situation, so my service should start with a clean session and no transaction opened
So whats the right way to setup database for my testcase?
© Stack Overflow or respective owner