Le programme d'installation de la base de données pour les tests Unitaires avec Spring, Hibernate et Spring Soutien à la Transaction
Je veux tester l'intégration de dao-couche avec mon service-couche dans un test unitaire. J'ai donc besoin de certaines données dans ma base de données (hsql). Pour cette configuration, j'ai besoin d'un propre transaction au début de mon cas de test pour s'assurer que toute mon installation est vraiment imprégné de la base de données avant de commencer mon cas de test.
Alors, voici ce que je veux réaliser:
//NotTranactional
public void doTest {
//transaction begins
setup database
//commit transaction
service.doStuff() //doStuff is annotated @Transactional(propagation=Propagation.REQUIRED)
}
Voici ma pas de code de travail:
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"
p:driverClassName="org.hsqldb.jdbcDriver"
p:url="jdbc:hsqldb:mem:posmail" p:username="sa"
p:password="" />
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>de.diandan.asynch.modell.receipt.Position</value>
<value>de.diandan.asynch.modell.receipt.Receipt</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.connection.useUnicode">true</prop>
<prop key="hibernate.connection.characterEncoding">UTF-8</prop>
<prop key="hibernate.connection.charSet">UTF-8</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<!-- Enable Hibernate's automatic session context management
<prop key="current_session_context_class">thread</prop> -->
<!-- Disable the second-level cache -->
<prop key="cache.provider_class">org.hibernate.cache.NoCacheProvider</prop>
<prop key="hibernate.show_sql">false</prop>
</props>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
Mon Cas De Test
@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() {
...
}
}
Menant à cette 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)
Je ne sais pas quel est le bon moyen de faire la transaction autour de l'installation de la base de données.
Ce que j'ai essayé:
@Before
@Transactional(propagation=Propagation.REQUIRED)
public void setup() {
setup database
}
-> le Printemps ne semble pas lancer la transaction dans le @Avant-annoté méthodes. Au-delà, ce n'est pas ce que je veux vraiment, car il y a beaucoup merhods dans mon testclass qui a besoin d'un peu différent de l'installation, donc j'ai besoin de plusieurs de init-méthodes.
@Transactional(propagation=Propagation.REQUIRED)
public void setup() {
setup database
}
public void doTest {
init();
service.doStuff() //doStuff is annotated @Transactional(propagation=Propagation.REQUIRED)
}
--> init semble pas à se lancer dans l'opération
Ce que je ne veux pas faire:
public void doTest {
//doing my own transaction-handling
setup database
//doing my own transaction-handling
service.doStuff() //doStuff is annotated @Transactional(propagation=Propagation.REQUIRED)
}
--> commencer à mélanger les ressorts de la transaction et de traitement de ma propre semble être une douleur dans le cul.
@Transactional(propagation=Propagation.REQUIRED)
public void doTest {
setup database
service.doStuff()
}
--> je veux tester aussi réel que possible de la situation, de sorte que mon service doit démarrer avec une nouvelle session et aucune transaction ouverte
Alors quel est le bon chemin pour l'installation de la base de données pour mon cas de test?
Oui, je suis en utilisant innodb
OriginalL'auteur mibutec | 2012-06-10
Vous devez vous connecter pour publier un commentaire.
Ajoutant des annotations a fait le tour:
Ici est la configuration complète:
OriginalL'auteur mibutec
Pour le printemps des tests orientés vous pouvez utiliser le printemps runner pour JUnit:
documenté ici:
http://static.springsource.org/spring/docs/3.0.0.M3/spring-framework-reference/html/ch10s03.html
Et la partie qui peut vous intéresser, c'est que vous êtes capable d'annoter des méthodes avec des annotations comme suit:
et
vous pouvez même utiliser quelque chose comme
pour indiquer que vous ne voulez pas de transaction appliquée. Mais être conscient de cette document avec l'avertissement suivant:
pourriez-vous fournir spring et hibernate configuration?
Ajout de la partie intéressante de mon ressort config. Mais je pense que la raison est visible dans la stack-trace: Il n'y a pas de proxy autour de ReceiptServiceTest.init. Quel est la raison?
En aparté: pendant ce temps, @NotTransactional a été dépréciées.
merci pour le commentaire, je l'ai ajouté à la réponse
OriginalL'auteur Francisco Spaeth