Turn your manual testers into automation experts Request a DemoStart testRigor Free

Liferay Testing

Liferay Testing

Liferay provides a wide range of services and products to support the development and deployment of enterprise portals and web applications. Its modular architecture allows developers to add or remove features as needed, and it comes with various pre-built portlets, themes, and templates to accelerate development.

Liferay is written in Java and utilizes the Java Servlet API and JavaServer Pages (JSP) technology. It operates on various application servers, such as Apache Tomcat, JBoss, and IBM WebSphere, and supports multiple databases, including MySQL, Oracle, and PostgreSQL.

Some of Liferay's services are free, while others are paid. Here are some examples:

  • Liferay Portal: This is the core product of the Liferay framework, providing a comprehensive platform for building and deploying web applications. Liferay Portal Community Edition is available as a free, open-source product, while Liferay Portal Enterprise Edition is a paid product offering additional features and support.
  • Liferay DXP: Liferay DXP (Digital Experience Platform) is a paid product that encompasses various enterprise features and capabilities, such as advanced personalization, analytics, marketing automation, and support for multiple sites and languages.
  • Liferay Cloud: This cloud-based platform offers hosting, management, and support for Liferay applications. It's a paid service that includes a range of deployment options, from public to private and hybrid cloud environments.
  • Liferay Consulting: Liferay provides paid consulting services to assist organizations with the design, development, and implementation of Liferay applications.
  • Liferay Training: Offering a variety of training courses and certifications for developers, administrators, and end-users, Liferay's educational resources are available both online and in-person, with some being free and others paid.
  • Liferay Marketplace: A repository for plugins and extensions for Liferay applications, the Marketplace features many free items, along with some that are paid.

Liferay also provides a comprehensive set of APIs for integration with other enterprise systems and services.

You can test your Liferay application code using the following techniques:

Unit Testing

Writing unit tests is a good practice to ensure that every unit of code in your application is giving the expected output. At the heart of testing, you need to perform certain actions and then assert the output. A good unit test makes sure that the test has only one reason to fail while checking just one thing. Unit tests are meant to be lightweight so that they can be run in isolation. This is usually achieved via mocking other components or modules in the application to avoid external dependencies.

Let's take a look at some of the known tools used to test Liferay application code.

Using JUnit

JUnit is a popular open-source testing framework for Java. JUnit provides a simple and easy-to-use API for defining test cases and running them, and it includes a range of features that make it easy to write comprehensive test suites.

JUnit provides a number of useful features for writing and running tests, including:

  • Annotations: JUnit uses annotations to identify methods that should be run as tests and to provide additional information about the tests.
  • Assertions: JUnit provides a range of assertion methods that allow developers to check whether certain conditions are true or false.
  • Test runners: JUnit provides a range of test runners that allow developers to run tests in different ways, such as running tests in parallel, running tests in a specific order, or running tests in a separate process.
  • Test fixtures: JUnit provides a range of tools for creating and managing test fixtures, such as setting up test data before running tests, or tearing down test data after running tests.

Here is an example of a JUnit test case for a HelloWorld class. The HelloWorld class has a method called getName which takes a User object as input and returns a string. The test verifies that the getName method of the HelloWorld class returns the expected value when given a specific User object.

The test uses Mockito to mock the UserLocalService and User objects. The UserLocalService is a Liferay service that provides access to user-related data, such as user profiles and account information. The User object represents a user in the Liferay portal. In this test, the BeanLocator and PortalBeanLocatorUtil classes are used to mock the UserLocalService object. The when method is used to specify the expected behavior of the mock objects. Finally, the assertEquals method is used to compare the expected value with the actual value returned by the getName method.
package com.test;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.junit.Test;
import com.liferay.portal.kernel.bean.BeanLocator;
import com.liferay.portal.kernel.bean.PortalBeanLocatorUtil;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.model.User;
import com.liferay.portal.service.UserLocalService;

public class HelloWorldTest {
  private final HelloWorld helloWorld = new HelloWorld();
  
  @Test
  public void testGetName()throws SystemException, PortalException { 

    // Mocking of Objects 
    BeanLocator beanLocator = mock(BeanLocator.class);
    PortalBeanLocatorUtil.setBeanLocator(beanLocator);
    
    UserLocalService userLocalService = mock(UserLocalService.class);
    User user = mock(User.class);
    
    when(beanLocator.locate(UserLocalService.class.getName())).thenReturn(userLocalService);
    when(userLocalService.getUser(1234)).thenReturn(user);
    when(user.getUserId()).thenReturn(1234L);
    when(user.getFirstName()).thenReturn("Jane");
    assertEquals("Ms Jane", helloWorld.getName(user));
  } 
}

Using Liferay Portal test packages and classes

Liferay offers a group of packages for testing Liferay code. This is a set of Java packages and classes that are designed specifically for testing Liferay-based applications. The framework includes utilities for setting up a test environment, creating test data, and running unit and integration tests.

Here are some of the key packages:

  • com.liferay.portal.kernel.test: This package includes a variety of testing utilities and helpers, such as classes for configuring the test environment, creating mock objects, and asserting test results.
  • com.liferay.portal.test: This package includes classes for setting up a testing environment for Liferay applications, such as creating a mock portal instance, deploying plugins, and initializing the database.
  • com.liferay.portal.search.test: This package includes classes for testing Liferay's search functionality, such as creating search indexes, executing search queries, and verifying search results.
  • com.liferay.portal.security.auth.test: This package includes classes for testing Liferay's authentication and authorization functionality, such as simulating user logins, checking user permissions, and managing user roles.
  • com.liferay.portal.service.test: This package includes classes for testing Liferay's service layer, such as invoking service methods, creating mock data, and verifying service responses.

These are just a few examples of the packages and classes included in the Liferay Portal Testing Framework. There are many more classes and utilities available for testing different aspects of Liferay-based applications.

Using Mockito

Mockito is a popular open-source mocking framework for Java. It is used for creating mock objects in unit tests. Mock objects are objects that simulate the behavior of real objects in a controlled way. They are useful for isolating the code being tested from its dependencies and providing a more controlled environment for testing.

By using Mockito, developers can focus on testing their code in isolation and without the need for external dependencies, which can make testing faster and more reliable. It is widely used in the Java ecosystem and is compatible with many popular testing frameworks such as JUnit and TestNG.

Using PowerMock

PowerMock is a Java framework that extends other popular testing frameworks such as JUnit and Mockito. It allows for the testing of code that is normally difficult to test, such as static, final, and private methods. PowerMock works by manipulating the bytecode of the classes being tested, which allows it to bypass certain restrictions that would normally make these types of tests impossible.

In addition to its core features, PowerMock also provides a number of utilities and tools to aid in testing, such as the ability to mock constructors and other types of object creation, the ability to test code that interacts with external systems and resources, and more. It can be used in conjunction with other testing frameworks to provide a more complete testing solution for Java applications.

Using TestNG

TestNG is a testing framework for Java that is inspired by JUnit and NUnit but with some additional functionality. It is designed to cover all categories of tests such as unit, functional, end-to-end, integration, etc. TestNG provides advanced features such as annotations, test dependencies, parameterization, data-driven testing, and parallel execution. It is widely used in the Java community for testing applications and is supported by popular IDEs such as Eclipse, IntelliJ IDEA, and NetBeans.

Integration Testing

Integration testing focuses on module integrations. Here too you can use techniques like mocking and dependency injection to reduce external dependencies. However, be sure to do this wisely since we want to exercise integrations of the modules under test. You can write integration tests using the same tools used for unit testing like JUnit, Mockito, Liferay test classes, and TestNG. However, there are some more tools that can be leveraged. They are mentioned below.

Using Arquillian

Arquillian is an integration testing framework that provides a simple way to write tests that interact with an application server or a web container. It allows developers to write and execute tests within the container, rather than having to set up and manage the container externally. This can greatly simplify the testing process and provide more accurate results.

Arquillian supports various types of containers, including Java EE containers, OSGi frameworks, and embedded containers. It also provides a flexible extension system that allows developers to customize the testing environment and behavior. Arquillian is often used in conjunction with other testing frameworks, such as JUnit or TestNG, to provide a complete testing solution for enterprise applications. Arquillian has a set of tools to test Liferay plugins called Arquillian Extension for Liferay.

Here is a test using Arquillian. It tests the add method of SampleService in a Liferay portlet environment. The @RunWith(Arquillian.class) marks the class for Arquillian to run. The testAdd method tests the add method of SampleService by injecting an instance of SampleService and invoking its add method with arguments. It then uses the Assert class to verify that the result is as expected.
package com.liferay.arquillian.test;

import com.google.common.io.Files;

import com.liferay.arquillian.containter.remote.enricher.Inject;
import com.liferay.arquillian.sample.service.SampleService;
import com.liferay.portal.kernel.exception.PortalException;

import java.io.File;
import java.io.IOException;

import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;

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

@RunWith(Arquillian.class)
public class BasicPortletIntegrationTest {

  @Deployment
  public static JavaArchive create() throws Exception {
    final File tempDir = Files.createTempDir();
    
    String gradlew = "./gradlew";
    
    String osName = System.getProperty("os.name", "");
    if (osName.toLowerCase().contains("windows")) {
        gradlew = "./gradlew.bat";
    }
    
    final ProcessBuilder processBuilder = new ProcessBuilder(
        gradlew, "jar", "-Pdir=" + tempDir.getAbsolutePath());
    
    final Process process = processBuilder.start();
    
    process.waitFor();
    
    final File jarFile = new File(
      tempDir.getAbsolutePath() +
        "/com.liferay.arquillian.sample-1.0.0.jar");
    
    return ShrinkWrap.createFromZipFile(JavaArchive.class, jarFile);
  }
  
  @Test
  public void testAdd() throws IOException, PortalException {
    final long result = _sampleService.add(5, 3);
  
    Assert.assertEquals(8, result);
  }
  
  @Inject
  private SampleService _sampleService;

}

Using Liferay Test Integration Bridge

Liferay Test Integration Bridge is a testing tool provided by Liferay that enables integration testing of Liferay applications. It is designed to be used with popular Java testing frameworks such as JUnit and TestNG. The Test Integration Bridge provides a set of classes and annotations that allow you to write tests that simulate requests to a Liferay portal and verify the responses that are generated. This makes it possible to test Liferay applications in a more realistic environment, as you can interact with the portal's various components (such as portlets, services, and themes) just as you would in a live deployment.

The Test Integration Bridge also provides a number of utility methods for setting up and tearing down test environments, as well as methods for interacting with various parts of the portal (such as users, roles, and permissions).

Some popularly used classes and utilities provided by the Liferay Test Integration Bridge are:

  • LiferayIntegrationTestRule: A JUnit TestRule that initializes the Liferay environment for integration testing.
  • PortalLifecycleUtil: A utility class for managing the Portal lifecycle during integration testing.
  • MockFacesContext: A class for mocking the JSF FacesContext object during testing.
  • MockHttpServletRequest: A class for mocking the HttpServletRequest object during testing.
  • MockHttpServletResponse: A class for mocking the HttpServletResponse object during testing.
  • MockLiferayPortletActionRequest: A class for mocking the LiferayPortletActionRequest object during testing.
  • MockLiferayPortletRenderRequest: A class for mocking the LiferayPortletRenderRequest object during testing.
  • MockLiferayPortletConfig: A class for mocking the LiferayPortletConfig object during testing.
  • MockLiferayPortletContext: A class for mocking the LiferayPortletContext object during testing.
  • MockLiferayPortletPreferences: A class for mocking the LiferayPortletPreferences object during testing.

Using Liferay DXP's @Inject annotation

With the help of @Inject, which comes from the LiferayIntegrationTestRule class, you can inject service components into an integration test. You need to create a @Rule in your class of type com.liferay.portal.test.rule.LiferayIntegrationTestRule, create a field to hold the service component (preferably a static field) and add the @Inject annotation. You can further specify a filter string or type parameter to specify the service component object to inject.

In the below example, we see how the test class injects a DDLServiceUpgrade object into a UpgradeStepRegistrator interface field.
public class Test {

  @ClassRule
  @Rule
  public static final AggregateTestRule aggregateTestRule = 
    new LiferayIntegrationTestRule();
  
  @Test
  public void testSomething() {
    // your test code here
  }
  
  @Inject(
    filter = "(&(objectClass=com.liferay.dynamic.data.lists.internal.upgrade.DDLServiceUpgrade))"
  )
  private static UpgradeStepRegistrator _upgradeStepRegistrator;

}

End-to-End Testing

End-to-end testing focuses on the end user’s view of interacting with the application. End users are not interested in what lies under the hood, but rather in how well the application responds and aids in fulfilling their needs. So we can say that end-to-end tests are in a way validating user journeys rather than the output of various units of code. This does not mean that code output is not important, but rather, the focus now shifts to the bigger picture, whether all these units are successfully able to come together to form the bigger picture.

Here are the most popular end-to-end testing framework choices:

  • Arquillian and Selenium
  • testRigor

Using Arquillian and Selenium

When it comes to end-to-end testing, you need to interact with the application like an actual user, that is, via a browser. Selenium is a popular choice for browser automation, and when used with other tools like Arquillian, it can automate tests easily.

Here is an example of a test case using these two tools. The @RunAsClient and @RunWith annotations indicate that this test is a web client that Arquillian will run. Like the integration test, the create method over here packages the test as a JAR file for execution by Arquillian. The testInstallPortlet() method tests if the portlet is correctly deployed to the portal by navigating to portlet's URL, getting the page source, and checking if the page contains the expected text.The test case uses @FindBy annotations to locate the relevant elements in the portlet's HTML markup. The _browser field is annotated with @Drone, which tells Arquillian to inject a WebDriver instance that can interact with the browser. The _portlerURL field is annotated with @PortalURL, which tells Arquillian to inject a URL instance that represents the URL of the portlet. And finally, the @test tells what needs to be tested during execution.
package com.liferay.arquillian.test;

import com.liferay.arquillian.portal.annotation.PortalURL;
import org.jboss.arquillian.drone.api.annotation.Drone;
import org.jboss.arquillian.junit.Arquillian;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;

@RunWith(Arquillian.class)
public class BasicPortletFunctionalTest {

  @Test
  public void testAdd() throws InterruptedException {
    _browser.get(_portletURL.toExternalForm());
    
    _firstParameter.clear();
    _firstParameter.sendKeys("5");
    
    _secondParameter.clear();
    _secondParameter.sendKeys("3");
    
    _add.click();
    
    Thread.sleep(5000);
    
    Assert.assertEquals("8", _result.getText());
  }
  
  @FindBy(css = "button[type=submit]")
  private WebElement _add;
  
  @Drone
  private WebDriver _browser;
  
  @FindBy(css = "input[id$='firstParameter']")
  private WebElement _firstParameter;
  
  @PortalURL("arquillian_sample_portlet")
  private URL _portletURL;
  
  @FindBy(css = "span[class='result']")
  private WebElement _result;
  
  @FindBy(css = "input[id$='secondParameter']")
  private WebElement _secondParameter;

}

Using testRigor

Take a look at the above example for an end-to-end test case. It's designed as a test for simple addition functionality but involves a lot of configuration, all expressed in code. So anyone who wants to write end-to-end tests needs to understand how to code and perform these initialization steps as well. But what if you could write your end-to-end tests without having to worry about these aspects, focusing instead on your test steps and assertions? You can easily achieve this with testRigor.

testRigor is an AI-powered automation tool that enables you to write tests in plain English. It also employs generative AI to further expedite test creation, crafting actual tests for you based solely on test case titles. Your test steps appear as simple English instructions given to the testRigor engine. The tool comes with an easy-to-use and intuitive user interface that enables you to configure complex settings like various integrations and execution-related specifications.

The testRigor platform greatly reduces the hassle of maintaining test suites thanks to the AI-powered engine that helps manage minor variations in UI element locators, so you can put your efforts into creating quality test cases. testRigor is a cloud-based platform and hence you need not worry about having to install it or set it up locally, though that is an option as well. With this tool, you can test across multiple platforms such as web, mobile and desktop.

You can perform regular browser and mobile interactions with ease while also testing more complex cases involving 2-factor authentication login, email testing, audio testing, visual testing, table data testing, accessibility testing and many more. This tool also supports mocking API calls, interacting with databases and creating test data.

Here's a simple example of an automated test case with testRigor:
open url "https://www.amazon.com"
check that page contains "Search Amazon.com"
enter "64GB drive" into "Search Amazon.com"
click "Go"
scroll down
grab value from "MAIN-SEARCH_RESULTS-5" and save it as "item1"
click on stored value "item1"
scroll down by 1/2 of the screen
select "2" from "Quantity:"
scroll up
click "Add to cart"
check that page contains "Added to cart"
grab value from "proceedToRetailCheckout" and save it as "button1"
check that stored value "button1" itself contains "2 items"
click by image from stored value "logo" with less than "10" % discrepancy

Conclusion

Liferay provides an excellent platform for developing applications, and coupling it with the right testing tools ensures that your application remains free of bugs.

Join the next wave of functional testing now.
A testRigor specialist will walk you through our platform with a custom demo.