Модульное тестирование в Liferay
Кто-нибудь знает, как запускать юнит-тесты для портлетов Liferay? Я нашел много сообщений об этом (например, http://agile-reflections.opnworks.com/2010/06/portlet-unit-testing-with-liferay-6.html), но, тем не менее, не работает.
3 ответа
Это может быть излишним, но если вы ищете корпоративный подход с непрерывным интеграционным тестированием, этот блог дает очень хороший пример: непрерывная интеграция в Liferay: запуск тестов Selenium 2 в пакете Tomcat 6
Модульное тестирование портлетов Liferay довольно сложно, когда используется ServiceBuilder.
Причина в том, что он генерирует довольно тяжелые сервисы, которые содержат ссылки не только на bean-объекты внутри Portlet, но даже на bean-компоненты Portal, генерируемые ServiceBuilder.
Есть такие инструменты, как InitUtil.init(); это позволяет вам по крайней мере создавать экземпляры и использовать объекты ServiceBuilder... но не EntityServices. Для этого вам нужно использовать SpringUtil.loadContext(); что требует
System.setProperty("external-properties", "testing.properties");
где testing.properties содержит:
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
Это определения пружин, которые будут загружены для тестирования контекста приложения. Все бы хорошо, но bean-компоненты из portlet-spring.xml - это те тяжелые сервисы, которые содержат ссылки на определения bean-компонентов Portal, такие как ResourceService, UserLocalService, CounterLocalService, и вам придется загружать даже META-INF/portal-spring.xml
и поверьте мне, это не так просто, потому что вам придется загружать много других вещей.
ОТВЕТ:
Правда в том, что вам, скорее всего, не понадобится юнит-тестирование служб SB портлета, никогда. Они представляют сущности с постоянством и уровнем обслуживания вокруг. То, что не должно быть проверено. Вы просто должны издеваться над ними и заглушить их методы, верно?
И лучший способ для тестирования юнитов и интеграций в отношении макетов - это не использовать статические классы *LocalServiceUtil в вашем приложении, потому что они практически не могут быть смоделированы.
Вам просто нужно создать Spring FactoryBean:
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;
Написание модульных / интеграционных тестов для этого портлета было бы довольно просто, верно? Вы просто создаете весенний контекст для тестирования и издеваетесь над этими сервисами:
Использование Service Builder того стоит, но вы должны иметь некоторые знания Spring и поиграть с ним некоторое время. Тогда это сэкономит много времени, потому что его легко обслуживать.
Вам нужно иметь сторонние библиотеки на classpath.
Ключевым моментом является наличие даже portal-impl.jar и других зависимостей портала от пути к классам и наличие InitUtil.initWithSpring(boolean);
загрузите основные конфигурации xml Spring, которые вы указали в spring-ext.properties в свойстве spring.congigs, только те сервисы, которые вам нужны. Возможно, вам не нужны никакие сервисы портала, а только портлетные, но это проблема, потому что ваши сервисы портлетов, генерируемые компоновщиком сервисов, используют сервисы портала.
Для использования сервис-компоновщика просто необходимы хорошие знания о весне и загрузке классов.
Но вы должны понимать инфраструктуру, прежде чем делать это. Требуется довольно много хаков...
BeanLocator beanLocator = new BeanLocatorImpl(PortalClassLoaderUtil.getClassLoader(), ac);
PortletBeanLocatorUtil.setBeanLocator("portlet", beanLocator);