Tests unitaires dans Liferay

Je viens de passer 2 ans en mission sur un projet basé sur le portail Liferay. Nous avons suivi les grands principes des méthodes agiles (Scrum notamment) et de ce fait réalisé un bon nombre de tests unitaires.  Afin de respecter LE grand principe des tests unitaires, à savoir ne pas du tout sortir de la méthode testée, nous avons dû notamment mocker (simuler) les appels static de Liferay (tel que UserLocalServiceUtil.method(), …). En effet, ces services utilisent généralement un bean spring qui va faire remonter notre appel dans les différentes couches de l’application, ce qui au final est tout sauf un appel unitaire …

Après quelques recherches sur le net, nous avons finalement découvert l’outil jMockIt dont voici un petit exemple très simple qui démontre comment simuler ces fameux appels static.

Tout d’abord, vous devez télécharger l’outil ici, puis ajouter le jar jmockit.jar à votre classpath.

Voici, dans un premier temps, la classe MyClass contenant une méthode que l’on souhaite tester :

 import com.liferay.portal.model.User; import com.liferay.portal.service.UserLocalServiceUtil;</code> public class MyClass { public String myTestMethod(long id) throws Exception { User user = UserLocalServiceUtil.getUser(id); if(user.getUserId()%2 == 0){ return "INACTIVE"; }else{ return "ACTIVE"; } } }

L’implémentation des objets du model Liferay n’est pas utilisable tel quel dans les tests unitaires. Il faut donc surcharger ces objets de la manière suivante :

 public class UserImplFake implements com.liferay.portal.model.User {</code> private long userId; private boolean active; //... A compléter selon vos besoins... @Override public int compareTo(User arg0) { return 0; } @Override public boolean getActive() { return active; } @Override public long getUserId() { return userId; } @Override public boolean isActive() { return active; } @Override public void setActive(boolean arg0) { active = arg0; } @Override public void setUserId(long arg0) { userId = arg0; } @Override public boolean getAgreedToTermsOfUse() { return false; } //... }

Tout est maintenant prêt pour écrire le test unitaire :

 import static org.junit.Assert.assertEquals; import mockit.Mock; import mockit.MockClass; import mockit.Mockit;</code> import org.junit.Test; import com.liferay.portal.PortalException; import com.liferay.portal.SystemException; import com.liferay.portal.model.User; import com.liferay.portal.service.UserLocalServiceUtil; public class ExampleTest { @Test public void test_MyTestMethod_idPair() throws Exception { Mockit.setUpMocks(MockUserLocalServiceUtil.class); MyClass test = new MyClass(); String myResult = test.myTestMethod(1234l); assertEquals("les utilisateurs d'id pair doivent être inactif","INACTIVE",myResult); } @Test public void test_MyTestMethod_idImpair() throws Exception { Mockit.setUpMocks(MockUserLocalServiceUtil.class); MyClass test = new MyClass(); String myResult = test.myTestMethod(1235l); assertEquals("les utilisateurs d'id impair doivent être actif","ACTIVE",myResult); } @MockClass(realClass = UserLocalServiceUtil.class) public static class MockUserLocalServiceUtil { @Mock public static User getUser(long userId) throws PortalException, SystemException { User user = new UserImplFake(); if(userId==1234){ user.setUserId(1234l); user.setActive(false); } if(userId==1235){ user.setUserId(1235l); user.setActive(true); } return user; } } }

Dans ce code, on demande à jMockit d’utiliser la classe MockUserLocalServiceUtil au lieu de la classe UserLocalServiceUtil uniquement pour la méthode getUser(long). Celle-ci se charge alors de renvoyer un objet utilisable dans un environnement clos.

Maintenant, essayez d’exécuter les tests unitaires.
L’erreur suivante doit alors apparaître :

<br></br>
java.lang.NoClassDefFoundError: Could not initialize class mockit.Mockit<br></br>
at com.ippon.blog.unittest.ExampleTest.test_MyTestMethod_idImpair(ExampleTest.java:32)

En effet, pour que tout fonctionne vous devez ajouter l’agent jmockit aux arguments de votre VM :
-javaagent:${project}\lib\jmockit.jar

Vos tests unitaires doivent maintenant passer au vert.

Sur notre projet nous avons également utilisé les classes offertes pas Spring dans le package org.springframework.mock.web.
Avec ces différents outils, les différentes couches de notre application ont pu être testées très facilement.

Vous pouvez trouver ici un article présentant un grand nombre des possibilités offertes par jmockit.


Vous avez trouvé cette publication utile? Cliquer sur
Ippon
Ippon est un cabinet de conseil en technologies, créé en 2002 par un sportif de Haut Niveau et un polytechnicien, avec pour ambition de devenir leader sur les solutions Digitales, Cloud et BigData.

Ippon accompagne les entreprises dans le développement et la transformation de leur système d’information avec des applications performantes et des solutions robustes.

Ippon propose une offre de services à 360° pour répondre à l’ensemble des besoins en innovation technologique : Conseil, Design, Développement, Hébergement et Formation.

Nous avons réalisé, en 2017, un chiffre d’affaires de 31 M€ en croissance organique de 30%. Nous sommes aujourd’hui un groupe international riche de plus de 320 consultants répartis en France, aux USA, en Australie et au Maroc.
FRANCE Website LinkedIn