How to develop Integration Test for liferay 7.2 service builder modules

In liferay 7.1 we have an article here that explain "Introduction to Testing ",  first of all  i suggest you read this useful document because in this post we just implement an module to testing a "Liferay Service Builder Module" Step-by-Step with famous "Foo" entity.

Lets Go!

Step 1 - Create a liferay workspace with blade CLI

First consider that you are using latest version of Blade CLI.

Create an empty directory with name liferay-ws-7.2 on your computer, got to this directory and initializing and empty workspace  by executing  bellow command.

blade  init -v 7.2

Then open that in your favorite IDE, i use IntelliJ IDEA.

Next, check your workspace settings :

  • .blade.properties

it should be like below :

liferay.version.default=7.2
profile.name=gradle

 

  • gradle.properties

you should have bellow  property in your file :

liferay.workspace.bundle.url=https://releases-cdn.liferay.com/portal/7.2.1-ga2/liferay-ce-portal-tomcat-7.2.1-ga2-20191111141448326.tar.gz
app.server.tomcat.version=9.0.17
liferay.workspace.target.platform.version=7.2.1
  • settings.gradle

Check dependencies version here.

buildscript {
    dependencies {
        classpath group: "com.liferay", name: "com.liferay.gradle.plugins.workspace", version: "2.2.11"
        classpath group: "net.saliman", name: "gradle-properties-plugin", version: "1.4.6"
    }

    repositories {
        maven {
            url "https://repository-cdn.liferay.com/nexus/content/groups/public"
        }
    }
}

apply plugin: "net.saliman.properties"

apply plugin: "com.liferay.workspace"

Now you have an suitable liferay work space to create a Service Builder Module!

Step 2 - Create Foo Service Builder Module

  • Create foo module with executing bellow command :
blade create -t service-builder -p ir.sain.example  -c FooPortlet foo

your foo module will be created on module directory

  • Then execute bellow command to generating service layer classes:
 .\gradlew buildService

The result :

> Task :modules:foo:foo-service:buildService
Building Foo
Writing src\main\java\ir\sain\example\service\persistence\impl\FooPersistenceImpl.java
Writing ..\foo-api\src\main\java\ir\sain\example\service\persistence\FooPersistence.java
Writing ..\foo-api\src\main\java\ir\sain\example\service\persistence\FooUtil.java
Writing src\main\java\ir\sain\example\model\impl\FooModelImpl.java
Writing src\main\java\ir\sain\example\model\impl\FooBaseImpl.java
Writing src\main\java\ir\sain\example\model\impl\FooImpl.java
Writing ..\foo-api\src\main\java\ir\sain\example\model\FooModel.java
Writing ..\foo-api\src\main\java\ir\sain\example\model\Foo.java
Writing src\main\java\ir\sain\example\model\impl\FooCacheModel.java
Writing ..\foo-api\src\main\java\ir\sain\example\model\FooWrapper.java
Writing ..\foo-api\src\main\java\ir\sain\example\model\FooSoap.java
Writing src\main\java\ir\sain\example\service\impl\FooLocalServiceImpl.java
Writing src\main\java\ir\sain\example\service\base\FooLocalServiceBaseImpl.java
Writing ..\foo-api\src\main\java\ir\sain\example\service\FooLocalService.java
Writing ..\foo-api\src\main\java\ir\sain\example\service\FooLocalServiceUtil.java
Writing ..\foo-api\src\main\java\ir\sain\example\service\FooLocalServiceWrapper.java
Writing src\main\java\ir\sain\example\service\impl\FooServiceImpl.java
Writing src\main\java\ir\sain\example\service\base\FooServiceBaseImpl.java
Writing ..\foo-api\src\main\java\ir\sain\example\service\FooService.java
Writing ..\foo-api\src\main\java\ir\sain\example\service\FooServiceUtil.java
Writing ..\foo-api\src\main\java\ir\sain\example\service\FooServiceWrapper.java
Writing src\main\java\ir\sain\example\service\http\FooServiceHttp.java
Writing src\main\java\ir\sain\example\service\http\FooServiceSoap.java
Writing src\main\resources\META-INF\module-hbm.xml
Writing src\main\resources\META-INF\portlet-model-hints.xml
Writing ..\foo-api\src\main\java\ir\sain\example\exception\NoSuchFooException.java
Writing src\main\java\ir\sain\example\service\persistence\impl\constants\FOOPersistenceConstants.java
Writing src\main\resources\META-INF\sql\indexes.sql
Writing src\main\resources\META-INF\sql\tables.sql
Writing src\main\resources\META-INF\sql\tables.sql
Writing src\main\resources\service.properties

BUILD SUCCESSFUL in 5s
1 actionable task: 1 executed
 
 

Next, create an add function in ir.sain.example.service.impl.FooLocalServiceImpl just  for testing.

@Override
    public Foo addFoo(
            long userId, String field1, boolean field2,int field3, Date field4, String field5, ServiceContext serviceContext)
            throws PortalException {

        // Foo

        User user = userLocalService.getUser(userId);
        long groupId = serviceContext.getScopeGroupId();

        long fooId = counterLocalService.increment();

        Foo foo = fooPersistence.create(fooId);

        foo.setUuid(serviceContext.getUuid());
        foo.setGroupId(groupId);
        foo.setCompanyId(user.getCompanyId());
        foo.setUserId(user.getUserId());
        foo.setUserName(user.getFullName());
        foo.setField1(field1);
        foo.setField2(field2);
        foo.setField3(field3);
        foo.setField4(field4);
        foo.setField5(field5);

        foo = fooPersistence.update(foo);

        // TODO: Resources

        // TODO: Asset

        // TODO: Workflow

        return foo;
    }
 
 

 

Again execute :

 

 
 
 
 
.\gradlew buildService

 The result :

> Task :modules:foo:foo-service:buildService
Building Foo
Writing ..\foo-api\src\main\java\ir\sain\example\service\FooLocalService.java
Writing ..\foo-api\src\main\java\ir\sain\example\service\FooLocalServiceUtil.java
Writing ..\foo-api\src\main\java\ir\sain\example\service\FooLocalServiceWrapper.java
Writing src\main\resources\service.properties

 

Step 3 - Create  Foo Test Module

  • First, Create an empty module with exciting bellow command :
blade create -t api -p ir.sain.example.test  foo-test
  • Then move foo-test module to foo directory in modules directory.

Do some changes :

  • change bnd.bnd
Bundle-Name: foo-test
Bundle-SymbolicName: ir.sain.example.test
Bundle-Version: 1.0.0
  • remove main directory in src directory.
  • replace buildService task in build.gradle in foo-service module with bellow task
buildService {
    apiDir = "../foo-api/src/main/java"
    testDir = "../foo-test/src/testIntegration/java"
}

 

Again execute :

 

 
 
 
 
.\gradlew buildService

 The result :

> Task :modules:foo:foo-service:buildService
Building Foo
Writing ..\foo-test\src\testIntegration\java\ir\sain\example\service\persistence\test\FooPersistenceTest.java
Writing src\main\resources\service.properties

BUILD SUCCESSFUL in 5s
1 actionable task: 1 executed

Now, service-builder will be create FooPersistenceTest class in your foo-test module.

Liferay Service Builder will generated PersistenceTest for all entities but you must implement Test classes for Srvice layer.
  • Change the build.gradle file in foo-test module to :
dependencies {
    testCompile group: "com.liferay", name: "com.liferay.petra.lang"
    testCompile group: "com.liferay", name: "com.liferay.petra.string"
    testCompile group: "com.liferay", name: "com.liferay.registry.api"
    testCompile group: "com.liferay.portal", name: "com.liferay.portal.kernel"
    testCompile group: "javax.portlet", name: "portlet-api"
    testCompile group: "junit", name: "junit"
    testCompile group: "org.apache.felix", name: "org.apache.felix.http.servlet-api", version: "1.1.2"
    testCompile group: "org.osgi", name: "org.osgi.core"
    testCompile group: "org.slf4j", name: "slf4j-api"
    testCompile group: "org.springframework", name: "spring-test"

    testIntegrationCompile group: "com.liferay", name: "com.liferay.arquillian.extension.junit.bridge", version: "1.0.19"
    testIntegrationCompile group: "com.liferay.portal", name: "com.liferay.portal.test", version: "6.2.5"
    testIntegrationCompile group: "com.liferay.portal", name: "com.liferay.portal.test.integration", version: "6.0.24"
    testIntegrationCompile group: "log4j", name: "log4j", version: "1.2.17"
    testIntegrationCompile project(":modules:foo:foo-api")
    testIntegrationCompile project(":modules:foo:foo-service")

    testModules group: "com.liferay", name: "com.liferay.arquillian.extension.junit.bridge.connector", version: "1.0.0"
    testModules group: "com.liferay", name: "com.liferay.sync.api", version: "5.0.6"
    testModules group: "com.liferay", name: "com.liferay.sync.service", version: "3.0.9"
    testModules group: "com.liferay.portal", name: "com.liferay.portal.test", version: "6.2.5"
    testModules group: "com.liferay.portal", name: "com.liferay.portal.test.integration", version: "6.0.24"
    testModules group: "org.apache.aries.jmx", name: "org.apache.aries.jmx.core", version: "1.1.7"
}

copyTestModules {
    dependsOn ":modules:foo:foo-api:deploy", ":modules:foo:foo-service:deploy"
}

setUpTestableTomcat {
    dependsOn ":initBundle"
}

 

  • Create FooLocalServiceTest class in ir.sain.example.service.test like bellow :

package ir.sain.example.service.test;
import com.liferay.arquillian.extension.junit.bridge.junit.Arquillian;
import com.liferay.portal.kernel.model.Group;
import com.liferay.portal.kernel.model.User;
import com.liferay.portal.kernel.service.ServiceContext;
import com.liferay.portal.kernel.test.rule.AggregateTestRule;
import com.liferay.portal.kernel.test.rule.DeleteAfterTestRun;
import com.liferay.portal.kernel.test.util.GroupTestUtil;
import com.liferay.portal.kernel.test.util.RandomTestUtil;
import com.liferay.portal.kernel.test.util.ServiceContextTestUtil;
import com.liferay.portal.kernel.test.util.TestPropsValues;
import com.liferay.portal.service.test.ServiceTestUtil;
import com.liferay.portal.test.rule.Inject;
import com.liferay.portal.test.rule.LiferayIntegrationTestRule;
import ir.sain.example.model.Foo;
import ir.sain.example.service.FooLocalService;
import org.junit.*;
import org.junit.runner.RunWith;

/**
 * @author Nader Jafari
 */
@RunWith(Arquillian.class)
public class FooLocalServiceTest {

    @ClassRule
    @Rule
    public static final AggregateTestRule aggregateTestRule =
            new LiferayIntegrationTestRule();

    @Before
    public void setUp() throws Exception {
        _group = GroupTestUtil.addGroup();
        _user = TestPropsValues.getUser();

        ServiceTestUtil.setUser(TestPropsValues.getUser());
    }

    @Test
    public void testAddFoo() throws Exception {
        int initialCount = _fooLocalService.getFoosCount();

        addFoo(_user.getUserId());

        int actualCount = _fooLocalService.getFoosCount();

        Assert.assertEquals(initialCount + 1, actualCount);
    }


    protected Foo addFoo(long userId)
            throws Exception {
        ServiceContext serviceContext =
                ServiceContextTestUtil.getServiceContext(
                        _group.getGroupId(), userId);

        return _fooLocalService.addFoo(
                userId, RandomTestUtil.randomString(),RandomTestUtil.randomBoolean(),
                RandomTestUtil.randomInt(), RandomTestUtil.nextDate(),RandomTestUtil.randomString(),
                serviceContext);
    }

    @DeleteAfterTestRun
    private Group _group;

    @Inject
    private FooLocalService _fooLocalService;

    private User _user;

}

 

Step 4 - Running Integration Test!

Now we are in exciting step!

excute bellow command in Work Space root directory,

This will (download and) start a Liferay instance, deploy the required modules and run the tests found in the test module.

F:\liferay\liferay-ws-7.2> .\gradlew testIntegration
Wait ... if you would like to running this step faster and safer download liferay-ce-portal-tomcat-7.2.1-ga2-20191111141448326.tar.gz and place in  YOUR_HOME_DIRECTORY\.liferay\bundles then run abbove command.
Congratulation !!!

if everything's go fine , you should see generated report in liferay-ws-7.2\modules\foo\foo-test\build\reports\tests\testIntegration

You could clone entire project from Here !

Special thank to Christian Berndt who helped me to write this post.

 

 

 

 

Blogs

Hi Nader!

Your post is very great, but does not work on my laptop becouse the port 8005 is already using.

Do you know any way to avoid download the bundle?

In this way, I can set it up in server.xml

Or maybe, do you know how to set up the bundle tomcat before starting?

It is driving me crazy.

Thank you very much for your time.