Plugin Tutorial: How to unit test a plugin

This tutorial shows you how to test your plugins in Vertical Site. By using Spring´s MockHttpServletRequest and -Response this becomes easy. The only thing is to know where to inject those mocks so that your plugin can use them. This tutorial shows you how for three types of plugins: controller plugin, http response filter plugin and function library plugin.

Testing a controller plugin

The plugin to test

This plugin´s purpose is to return a welcome message based on a name given as a request parameter.

import com.enonic.cms.api.plugin.HttpControllerPlugin;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyControllerPlugin extends HttpControllerPlugin {

    public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {

        String name = request.getParameter("name");
        String content = "Welcome " + name;

        response.setContentType("text/plain");
        response.setContentLength(content.getBytes().length);
        response.getWriter().print(content);
    }
}

The unit test

import static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.Test;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;


public class MyControllerPluginTest {

    MyControllerPlugin plugin;
    MockHttpServletRequest request;
    MockHttpServletResponse response;

    @Before
    public void before() throws Exception {

        // setup mock objects for each test
        request = new MockHttpServletRequest();
        response = new MockHttpServletResponse();
        plugin = new MyControllerPlugin();
    }

    @Test
    public void testResponseContent() throws Exception {

        // setup 
        request.setParameter("name", "Martin");

        // exercise
        plugin.handleRequest(request, response);

        // verify
        assertEquals("text/plain", response.getContentType());
        assertEquals("Welcome Martin", response.getContentAsString());
    }
}

Testing a http response filter plugin

The plugin to test

This plugin´s purpose is to replace a specific string with the IP address of the remote client.

import com.enonic.cms.api.plugin.HttpResponseFilterPlugin;

import javax.servlet.http.HttpServletRequest;

public class MyHttpResponseFilterPlugin extends HttpResponseFilterPlugin {

    private final static String TAG_TO_REPLACE = "##ip##";

    public String filterResponse(HttpServletRequest request, String textResponse, String contentType) {

        String remoteAddress = request.getRemoteAddr();
        return textResponse.replaceAll(TAG_TO_REPLACE, remoteAddress);
    }
}

The unit test

import static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.Test;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;

public class MyHttpResponseFilterPluginTest {

    MyHttpResponseFilterPlugin plugin;
    MockHttpServletRequest request;
    MockHttpServletResponse response;

    @Before
    public void before() throws Exception {

        // setup mock objects for each test
        request = new MockHttpServletRequest();
        response = new MockHttpServletResponse();
        plugin = new MyHttpResponseFilterPlugin();
    }

    @Test
    public void testIpReplacement() throws Exception {

        // setup
        request.setRemoteAddr("10.0.0.45");
        String textResponse = "Client's IP is ##ip##";
        String contentType = "text/plain";

        // exercise
        String filteredResponse = plugin.filterResponse(request, textResponse, contentType);

        // verify
        assertEquals("Client's IP is 10.0.0.45", filteredResponse);
    }
}

Testing a function library plugin

The plugin to test

This plugin´s purpose is to create a content based on different parameters given on the request. To create the content the plugin uses the client api.

import com.enonic.cms.api.client.ClientFactory;
import com.enonic.cms.api.client.LocalClient;
import com.enonic.cms.api.client.model.CreateContentParams;
import com.enonic.cms.api.client.model.content.ContentDataInput;
import com.enonic.cms.api.client.model.content.ContentStatus;
import com.enonic.cms.api.plugin.PluginEnvironment;
import javax.servlet.http.HttpServletRequest;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;

public class MyFunctionLibraryPlugin  {

    public static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm");

    public int createContent() throws ParseException {

        HttpServletRequest request = PluginEnvironment.getInstance().getCurrentRequest();
        LocalClient client = ClientFactory.getLocalClient();


        CreateContentParams params = new CreateContentParams();
        params.categoryKey = Integer.valueOf(request.getParameter("categoryKey"));
        params.status = ContentStatus.STATUS_APPROVED;
        params.publishFrom = DATE_FORMAT.parse(request.getParameter("publishFrom"));

        ContentDataInput contentData = new ContentDataInput("MyContentType");
        //..continue to fill out
        params.contentData = contentData;

        return client.createContent(params);        
    }
}

The unit test

The challenge of unit testing this plugin is to simulate the LocalClient.createContent function. I will do this by using the MockLocalClient class available in the package com.enonic.cms.api.mock. You could also use EasyMock or something similar to make it more flexible. The MockLocalClient is a just dummy implementation of the LocalClient interface. Notice also the MockPluginEnvironment which you have to use to make PluginEnvironment.getInstance() work in your plugin.

import com.enonic.cms.api.client.ClientFactory;
import com.enonic.cms.api.client.model.CreateContentParams;
import com.enonic.cms.api.client.model.content.ContentStatus;
import com.enonic.cms.api.mock.MockLocalClient;
import com.enonic.cms.api.mock.MockPluginEnvironment;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import org.junit.Before;
import org.junit.Test;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import java.util.GregorianCalendar;

public class MyFunctionLibraryPluginTest {

    MyFunctionLibraryPlugin plugin;
    MockHttpServletRequest request;
    MockHttpServletResponse response;
    MockLocalClient client;
    MockPluginEnvironment pluginEnvironment;

    @Before
    public void before() throws Exception {

        // setup mock objects for each test
        request = new MockHttpServletRequest();
        response = new MockHttpServletResponse();
        plugin = new MyFunctionLibraryPlugin();

        pluginEnvironment = new MockPluginEnvironment();
        pluginEnvironment.setCurrentRequest(request);

    }

    @Test
    public void testResponseContent() throws Exception {

        // setup
        request.setParameter("categoryKey", "101");
        request.setParameter("publishFrom", "2008-06-13 13:13");

        // setup a mock of the Local Client
        client = new MockLocalClient() {
            public int createContent(CreateContentParams params) {
                // verify method is called with expected params
                assertEquals(ContentStatus.STATUS_APPROVED, params.status);
                assertEquals(101, params.categoryKey);
                assertEquals(new GregorianCalendar(2008, 5, 13, 13, 13).getTime(), params.publishFrom);
                assertNull(params.publishTo);                
                // return contentKey
                return 13;
            }
        };
        ClientFactory.setLocalClient(client);
        
        // exercise
        int contentKey = plugin.createContent();

        // verify that contentkey is returned
        assertEquals(13, contentKey);
    }
}

Comments

24 June 2008 13:16

Commented by Vetle Roeim

It should be noted that MockPluginEnvironment is not in 4.2.4, but will be available in 4.2.5 or 4.3. To avoid PluginEnvironment.getInstance() returning a null value, you can do "PluginEnvironmentImpl pei = new PluginEnvironmentImpl();" in your test to instantiate an instance of PluginEnvironment.

If you want to comment on this article you need to be logged in.

Published in 2011

2010

2009

2008

2007