2011-01-18 2 views
4

Est-ce que quelqu'un sait comment exécuter des tests unitaires pour les portlets Liferay? J'ai trouvé beaucoup de messages à ce sujet (par exemple http://agile-reflections.opnworks.com/2010/06/portlet-unit-testing-with-liferay-6.html) mais aucun ne fonctionne néanmoins.Tests unitaires dans Liferay

+0

Voulez-vous à l'unité de tester vos propres portlets ou Liferay construit dans portlets ? – blank

+0

Je souhaite tester mes propres portlets à l'aide de services créés par moi via Service Builder. – brandizzi

Répondre

0

You need to have some third party libraries on classpath. Le point clé est d'avoir même portal-impl.jar et d'autres dépendances de portail sur classpath et d'avoir InitUtil.initWithSpring(boolean); charger les configs core spring xml que vous spécifiez dans spring-ext.properties dans la propriété spring.congigs, seulement les services dont vous avez besoin . Vous n'avez peut-être pas besoin de services de portail et uniquement ceux du portlet, mais cela pose problème car vos services de portlet générés par le service de construction utilisent les services de portail. L'utilisation de service builder nécessite juste une bonne connaissance du ressort et de la charge de classes.

Mais vous devez comprendre l'infrastructure avant de le faire. Il y a beaucoup de hacks nécessaires ... Comme

BeanLocator beanLocator = new BeanLocatorImpl(PortalClassLoaderUtil.getClassLoader(), ac); 
PortletBeanLocatorUtil.setBeanLocator("portlet", beanLocator); 
+0

J'essaie de comprendre ce code encore :) Je vais le commenter après avoir obtenu quelque chose qui fonctionne. – brandizzi

0

tests unitaires Liferay portlets est assez compliqué quand ServiceBuilder est utilisé.

La raison en est qu'il génère des services assez lourds qui contiennent des références non seulement aux beans du portlet, mais aussi aux beans Portal générés par ServiceBuilder.

Il existe des outils tels que InitUtil.init(); Cela vous permet au moins d'instancier et d'utiliser les entités ServiceBuilder ... et non EntityServices. Pour cela, vous devez utiliser SpringUtil.loadContext(); qui exige

System.setProperty("external-properties", "testing.properties"); 

où testing.properties contient:

spring.configs=META-INF/ext-spring.xml,\ 
      META-INF/base-spring.xml,\ 
      META-INF/dynamic-data-source-spring.xml,\ 
      META-INF/infrastructure-spring.xml,\ 
      META-INF/shard-data-source-spring.xml,\ 
      META-INF/hibernate-spring.xml,\ 
      META-INF/portlet-spring.xml 

Ce sont des définitions de printemps à charger pour le contexte de l'application de test. Tout serait OK, mais les haricots de portlet-spring.xml sont ces services lourds contenant des références aux définitions de bean Portal comme ResourceService, UserLocalService, CounterLocalService et vous devrez charger même META-INF/portal-spring.xml et croyez-moi, ce n'est pas si simple que ça. Je dois charger beaucoup d'autres choses.

LA RÉPONSE:

La vérité est que vous aurez probablement pas à tester l'unité des services portlet SB, jamais. Ils représentent des entités avec la persistance et la couche de service autour. Quelque chose qui ne doit pas être testé. Vous avez juste à se moquer d'eux et à bout de leurs méthodes, non? Et la meilleure façon pour les tests de junit et d'intégration de se moquer n'est pas d'utiliser * LocalServiceUtil classes statiques dans votre application, car il est presque impossible de le débloquer.

Il vous suffit de créer un FactoryBean de printemps:

public class PortalFactoryBean implements FactoryBean { 
    private Class type; 

    public void setType(final Class type) { 
     this.type = type; 
    } 

    @Override 
    public Object getObject() throws Exception { 
     return PortalBeanLocatorUtil.locate(type.getName()); 
    } 

    @Override 
    public Class getObjectType() { 
     return type; 
    } 
} 

public class PortletFactoryBean implements FactoryBean { 
    private Class type; 

    public void setType(final Class type) { 
     this.type = type; 
    } 

    @Override 
    public Object getObject() throws Exception { 
     return PortletBeanLocatorUtil.locate(type.getName()); 
    } 

    @Override 
    public Class getObjectType() { 
     return type; 
    } 
} 

<bean id="somePortalBean" class="example.spring.PortalFactoryBean" lazy-init="true"> 
    <property name="type" value="com.liferay.some.util.SomeService"/> 
</bean> 

<bean id="somePortletBean" class="example.spring.PortletFactoryBean" lazy-init="true"> 
    <property name="type" value="com.example.SomeService"/> 
</bean> 

@Autowired 
private SomeService somePortalBean; 

tests unitaires d'écriture/intégration pour ce portlet serait assez facile, non? Vous venez de créer un contexte de printemps pour tester et vous vous moquez de ces services:

Builder Utilisation du service est la peine, mais vous devez avoir une certaine connaissance du printemps et jouer avec lui pendant un certain temps. Ensuite, il ménage beaucoup de temps car il est facile à entretenir.

+0

C'est une solution élégante mais ... Est-ce vraiment moqueur d'une telle solution universelle? Je ne vois pas comment je pourrais l'utiliser pour tester [requêtes personnalisées] (http://www.liferay.com/pt/community/wiki/-/wiki/Main/Custom+queries+in+Liferay+5.2) ou certains méthode utilisant une requête dynamique dans un service, par exemple. Ces méthodes sont fréquentes, au moins dans mon code, devrait certainement être testé et ne sont pas assez faciles à se moquer, non? Néanmoins, votre réponse est bonne et utile pour diverses situations en ce moment de toute façon. – brandizzi

+0

Vous avez raison, eh bien la dernière fois que j'ai construit portal-impl/test et l'ai mis en test testpath et j'ai appelé ServiceTestUtil.initPermissions() et ServiceTestUtil.initServices() avec portal.properties qui liste toutes les définitions META-INF/spring .xml et je les ai tous chargés + mon ext-spring où j'ai mis des haricots de mon contexte de portlet. Cela fonctionnera car il y a certainement tous les haricots chargés, mais c'est extrêmement lent. Plus que vous devez renommer META-INF dans votre portlet parce que si vous l'avez sur votre classpath aussi, il couvrirait le Portal. C'est beaucoup de travail man – lisak

+0

Exactement ... Prochain projet, je vais éviter d'utiliser ServiceBuilder pour voir les avantages qui en découlent, si cela vaut la peine ou pas ... – lisak