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.