How to write integration test for service builder generated classes in portlet plugins

Recently LCS team had really hard time with writing integration tests for service builder generated classes. Arquillian test patterns written for core portal plugin simply didn't work for our case and mocking service layer was pointles. As time passed by and code base grow we simply got angry and decided to stop with all development untill we are not able to run test as any other decent software engineer in the world.

Here I'll write exact steps we did in our EE PLUGINS SDK 6.2 and Liferay Portal EE 6.2 SP10 to make Arquillian tests work for us. Of course without help from awesome core engineering team which filled some gaps in the SDK infrastructure even this wouldn't be possible.

Step 1 - unzip new tomcat

I do this from my portal's source home directory:

ant -f build-dist.xml unzip-tomcat

Step 2 - manager webapp

Once you have fresh, clean tomcat in bundles directory (or whatever directory you use), you have to make sure there is manager webapp present. Arquillian uses manager application to deploy your plugin so it is required. I usually go to tomcat download site, download archive, and extract manager app from it.

Step 3 - modifiy setenv.sh

Go to TOMCAT_HOME/bin directory and add this line after original CATALINA_OPTS definition:

CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=8099 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false"

Step 4 - modify tomcat-users.xml

<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>

<role rolename="tomcat"/>
<role rolename="manager-gui"/>
<role rolename="manager-script"/>
<role rolename="manager-jmx"/>
<role rolename="manager-status"/>
  
<user password="tomcat" roles="tomcat,manager-gui,manager-script,manager-jmx,manager-status" username="tomcat"/>

</tomcat-users>

Step 5 - prepare database and compile portal

Dedicate new database instance (ieg. lportalee62x_test) for your integration tests and set it in portal-ext.properties and run from portal source home directory:

ant all

After ant task is completed you have portal environment ready for tests. You may wonder why I do all this like idiot? Well, because each time some plugin or some setting either destroys attempt of testing either wastes couple hours of my time until I find the problem. So each time I run tests in completely fresh environment.

Step 6 - Initalize portal infrastructure

Start portal once to initalize DB, download market-place plugin etc. Once you are surre everything is there deploy portlet plugin you want to test (you may need to deploy other dependencies also). After your plugin initalizes its own DB space, undeploy it. Again, you will question yourself if everything is OK with me - yes, don't worry, you will avoid million unexplainable issues if you follow this steps.

In this moment you have enviriontment ready to test.

Configure portlet plugin for integration test with Arquillian

Step 7 - declare dependecies in ivy.xml

<?xml version="1.0"?>
<ivy-module version="2.0" xmlns:m2="..." xmlns:xsi="..." xsi:noNamespaceSchemaLocation="...">
	<info module="my-portlet" organisation="com.liferay">
		<extends ... />
	</info>

	<dependencies defaultconf="default">
		<dependency conf="test->default" name="arquillian-junit-container" org="org.jboss.arquillian.junit" rev="1.1.6.Final" />
		<dependency conf="test->default" name="arquillian-tomcat-remote-7" org="org.jboss.arquillian.container" rev="1.0.0.CR6" />
		<dependency conf="test->default" name="com.liferay.ant.arquillian" org="com.liferay" rev="1.0.1" />
		<dependency conf="test->default" name="javassist" org="org.javassist" rev="3.17.1-GA" />
	</dependencies>
</ivy-module>

Step 8 - create arquilian.xml

Create PLUGIN_HOME_DIR/test/integration directory and place arquillian.xml file in it. Content should look like this:

<?xml version="1.0"?>
<arquillian xmlns="..." xmlns:xsi="..."	xsi:schemaLocation="...">
	<container qualifier="tomcat" default="true">
		<configuration>
			<property name="jmxPort">8099</property>
			<property name="pass">tomcat</property>
			<property name="user">tomcat</property>
		</configuration>
	</container>
</arquillian>

Step 9 - write an test

Here is one simple test, placed into PLUGIN_HOME/test/integration/com/my/package:

import org.jboss.arquillian.junit.Arquillian;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;

/**
 * @author Igor Beslic
 */
@RunWith(Arquillian.class)
public class LCSProjectServiceTest {
	@Test
	public void testAddDefaultLCSProject() throws Exception {
		LCSProject lcsProject = LCSProjectServiceUtil.addDefaultLCSProject();

		Assert.assertEquals(
			LCSConstants.CORP_PROJECT_DEFAULT_NAME, lcsProject.getName());

		List lcsClusterEntries =
			LCSClusterEntryLocalServiceUtil.getLCSProjectLCSClusterEntries(
				lcsProject.getLcsProjectId());

		Assert.assertTrue(lcsClusterEntries.size() == 1);

		LCSClusterEntry lcsClusterEntry = lcsClusterEntries.get(0);

		Assert.assertEquals(
			LCSConstants.LCS_CLUSTER_ENTRY_DEFAULT_NAME,
			lcsClusterEntry.getName());
	}
}

Step 10 - run test

I always run test against one class because my work day is not endless, and I have no infinite amount of RAM to avoid PermGen. I leave the rest of work to QA and I just do this:

test-class -Dtest.class=LCSProjectServiceTest

Step 11 - observe with connected services at lcs.liferay.com

Optionally, you can download lcs-portlet from lcs.liferay.com and deploy to your test portal. If correctly connected to LCS system, it would stream service statistics to LCS where you would be able to analyse it. More about it read in Marko's blog on how to monitor user expirence

Blogs
Great article Igor!!! Could you write the same article using Maven?
Really good blog post Igor! Very nice you can use the tools for testing!
Hi Manu, we made check for CE also. Seems that arquillian dependencies ivy setup is slightly different in plugins SDK CE, but once we confirm the settings I'll post CE settings for our community.