Bonjour,
J'utilise actuellement sur mon projet Spring 3.1.1 + Hibernate 3 + JUnit 4.
J'effectue actuellement des tests unitaires sur ma couche metier (et non sur la couche DAO) et je rencontre quelques difficultés liées aux transactions puisque j'ai une exception qui me pète à la gueule en me disant :
Le problème ne vient pas de mon bean puisque mon projet tourne mais du test unitaire que je n'arrive pas à faire fonctionner correctement.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [fr.gouv.travail.gestionAccords.server.business.gestionDossiers.detailsDossier.coordonees.implementations.AdresseBusinessImpl] is defined: expected single bean but found 0: at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:271) at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1101) at fr.gouv.travail.gestionAccords.server.business.gestionDossiers.detailsDossier.AdresseBusinessUnitTest.save(AdresseBusinessUnitTest.java:36) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) 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.InvokeMethod.evaluate(InvokeMethod.java:20) 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:49) 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:50) 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)
Voici le bean en question :
Le bean DAO :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 @Named("adresseBusinessBean") public class AdresseBusinessImpl implements IAdresseBusiness { @Inject private IAdresseDAO adresseDao; @Inject private DozerBeanMapper mapper; @Override public List<AdresseDTO> findAll() { return ServerTools.convert(mapper, adresseDao.findAll(), AdresseDTO.class); } @Override public List<AdresseDTO> findById(List<AdresseBean> adresseBeanList) { return ServerTools.convert(mapper, adresseDao.findById(adresseBeanList), AdresseDTO.class); } @Override @Transactional(propagation=Propagation.REQUIRED) public void save(AdresseBean adresseBean) { //.. Du code metier... adresseDao.save(adresseBean); // Du code metier... } ... }
Et enfin, mon test unitaire sous JUnit 4 :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 @Named("adresseDao") public class AdresseDAOImpl extends HibernateDaoSupport implements IAdresseDAO { @Inject public AdresseDAOImpl(SessionFactory sessionFactory) { super.setSessionFactory(sessionFactory); } @SuppressWarnings("unchecked") public List<AdresseBean> findAll() { List<AdresseBean> beanList = getHibernateTemplate().find("from AdresseBean"); if(logger.isDebugEnabled()) { logger.debug("Result(s) found : "); for(AdresseBean bean : beanList) { logger.debug(bean.toString()); } } return beanList; } @Transactional(propagation=Propagation.MANDATORY) public void save(AdresseBean adresseBean) { getHibernateTemplate().save(adresseBean); } ...
Vous aurez remarqué que j'ai mis une propagation à REQUIRED dans ma couche BUSINESS et une propagation à MANDATORY dans mon DAO.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations={"file:src/applicationContext.xml"}) @TransactionConfiguration(defaultRollback=true) public class AdresseBusinessUnitTest extends AbstractTransactionalJUnit4SpringContextTests { @Test public void save() { IAdresseBusiness adresseBusiness = (IAdresseBusiness)applicationContext.getBean(AdresseBusinessImpl.class); /** Initialise un bean avec différentes valeurs **/ AdresseBean adrBean = (AdresseBean)applicationContext.getBean(AdresseBean.class); adrBean.setCodeCommune("75016"); adrBean.setCodePostal("75016"); adrBean.setComplementVoie("Complément de la voie"); adrBean.setLibelleVoie("Libellé de la voie"); adrBean.setNumeroVoie(29); adrBean.setRepetitionVoie("BIS"); adrBean.setTypeVoie("All"); String ville = "Paris"; adrBean.setVille(ville); /** Sauvegarde du bean précédent **/ adresseBusiness.save(adrBean); /** Vérifie que le bean a bien été stocké en base **/ List<AdresseDTO> dtoList = adresseBusiness.findByVille(adrBean); Assert.notNull(dtoList); Assert.notEmpty(dtoList); Assert.isTrue(dtoList.get(0).getVille().equals(ville), "Attention, valeur attendue = '"+ville+"', obtenu :'"+dtoList.get(0).getVille()+"'!"); }
Mon transaction manager s'appelle "transactionManager", donc je n'ai pas vu la nécessité d'ajouter l'attribut portant le même nom.
Cela tourne très bien dans mon projet, mais JUnit n'a pas l'air d'aimer d'autant plus que si je supprime le :
de ma couche BUSINESS, alors ça fonctionne !
Code : Sélectionner tout - Visualiser dans une fenêtre à part @Transactional(propagation=Propagation.REQUIRED)
C'est à ne rien comprendre...
Alors auriez-vous, SVP, une idée ?
Merci d'avance pour vos retours et désolé pour la longueur de mon post !
PS : Je suis débutant en Spring + Hibernate + JUnit.
Partager