org.opencms.flex.TestCmsFlexResponse Maven / Gradle / Ivy
Show all versions of opencms-test Show documentation
/*
* This library is part of OpenCms -
* the Open Source Content Management System
*
* Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* For further information about Alkacon Software GmbH & Co. KG, please see the
* company website: http://www.alkacon.com
*
* For further information about OpenCms, please see the
* project website: http://www.opencms.org
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.opencms.flex;
import org.opencms.file.CmsObject;
import org.opencms.main.OpenCms;
import org.opencms.test.OpenCmsTestCase;
import org.opencms.test.OpenCmsTestProperties;
import org.opencms.util.CmsRequestUtil;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import junit.extensions.TestSetup;
import junit.framework.TestSuite;
/**
* Unit tests for the {@link CmsFlexResponse}.
*
* This test suite performs way more set-up than is required for the amount of testing that is done.
* However, there is probably value in demonstrating how to set up a test case to access flex cache resources
* so that more robust unit tests can be developed here.
*
* @since 6.0.1
*/
public class TestCmsFlexResponse extends OpenCmsTestCase {
/**
* An InvocationHandler which simply records the arguments for each method that was called.
*
* If a 'stub' object was passed in the contructor, and the stub object has a method of the
* same signature as the one that is being called, that method will be invoked.
*/
public static class RecordingMock implements InvocationHandler {
/** Maps {@link Method} to a {@link List} of arguments passed to each invocation of that method handled by this object. */
HashMap m_invocations = new HashMap();
/** If non-null, delegate method invocations to this object when possible. */
Object m_stub;
/**
* Default empty construtor.
*/
public RecordingMock() {
// noop
}
/**
* Construtor with a 'stub' Object.
*
* @param stub the stub Object to use
*/
public RecordingMock(Object stub) {
m_stub = stub;
}
/**
* Returns a list of all recorded calls to the given method.
*
* @param method the method to get the recorded calls for
*
* @return a list of all recorded calls to the given method
*/
public List getCalls(Method method) {
ArrayList calls = (ArrayList)m_invocations.get(method);
if (calls == null) {
calls = new ArrayList();
m_invocations.put(method, calls);
}
return calls;
}
/**
* Notice that the given method has been invoked.
*
* Two actions are taken:
*
* - The invocation is recorded in
{@link #getCalls getCalls(method)}
.
* - If {@link #m_stub} is not null, the requested method is invoked on it
*
*
* @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// record the invocation
getCalls(method).add(args);
// check to see if our stub object supports this method.
if (m_stub != null) {
Method stubMethod = null;
try {
stubMethod = m_stub.getClass().getMethod(method.getName(), method.getParameterTypes());
if (stubMethod != null) {
if (stubMethod.getReturnType() == null) {
if (method.getReturnType() != null) {
stubMethod = null;
}
} else if (!stubMethod.getReturnType().equals(method.getReturnType())) {
stubMethod = null;
}
}
} catch (NoSuchMethodException e) {
// ignore
} catch (SecurityException e) {
// ignore
}
// if stubMethod is not null, then stub object has a public method with the requested signature
if (stubMethod != null) {
return stubMethod.invoke(m_stub, args);
}
}
return null;
}
}
/**
* A partial implementation of {@link HttpServletRequest} which allows for the setting and getting of request attributes.
*/
public static class RequestStub {
/** Attribute map. */
HashMap m_attributes = new HashMap();
/**
* Returns the named attribute value.
*
* @param name the name of the attribute to return
* @return the value of the attribute
*/
public Object getAttribute(String name) {
return m_attributes.get(name);
}
/**
* Removes the named attribute.
*
* @param name the name of the attribute to remove
*/
public void removeAttribute(String name) {
m_attributes.remove(name);
}
/**
* Sets the named attribute to the given value.
*
* @param name the name of the attribute to set
* @param value the value to set
*/
public void setAttribute(String name, Object value) {
m_attributes.put(name, value);
}
}
/** Method for setContentType(String) from the HttpServletResponse class. */
static Method SET_CONTENT_TYPE;
/** Flex controller to be used by the tests. */
private CmsFlexController m_controller;
/** Request mockup object. */
private RecordingMock m_reqMock;
/** Response mockup object. */
private RecordingMock m_resMock;
/** Servlet request to use with the tests. */
private HttpServletRequest m_request;
/** Servlet response to use with the tests. */
private HttpServletResponse m_response;
/**
* Default JUnit constructor.
*
* @param arg0 JUnit parameters
*/
public TestCmsFlexResponse(String arg0) {
super(arg0);
}
/**
* Static initializer for this test case.
*/
static {
try {
SET_CONTENT_TYPE = HttpServletResponse.class.getMethod("setContentType", new Class[] {String.class});
} catch (NoSuchMethodException e) {
throw new RuntimeException("HttpServletResponse linkage error", e);
}
}
/**
* Test suite for this test class.
*
* @return the test suite
*/
public static TestSetup suite() {
OpenCmsTestProperties.initialize(org.opencms.test.AllTests.TEST_PROPERTIES_PATH);
TestSuite suite = new TestSuite();
suite.setName(TestCmsFlexResponse.class.getName());
suite.addTest(new TestCmsFlexResponse("testContentTypeRules"));
TestSetup wrapper = new TestSetup(suite) {
@Override
protected void setUp() {
setupOpenCms("simpletest", "/");
}
@Override
protected void tearDown() {
removeOpenCms();
}
};
return wrapper;
}
/**
* Convenience method to create a mock {@link HttpServletRequest} backed by the given invocation handler.
*
* @param recorder the mock recorder
*
* @return the new created request
*/
private static HttpServletRequest createMockRequest(RecordingMock recorder) {
return (HttpServletRequest)createProxy(HttpServletRequest.class, recorder);
}
/**
* Convenience method to create a mock {@link HttpServletResponse} backed by the given invocation handler.
*
* @param recorder the mock recorder
*
* @return the new created response
*/
private static HttpServletResponse createMockResponse(RecordingMock recorder) {
return (HttpServletResponse)createProxy(HttpServletResponse.class, recorder);
}
private static Object createProxy(Class interfaceClass, InvocationHandler handler) {
return Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(),
new Class[] {interfaceClass},
handler);
}
/**
* Test semantics for Content-Type header on
* {@link CmsFlexResponse#setContentType(String)} and {@link CmsFlexResponse#setHeader(String, String)}.
*
* @throws Exception if the test fails
*/
public void testContentTypeRules() throws Exception {
// test that non-top elements won't try to set the content type.
CmsFlexResponse f_res = new CmsFlexResponse(m_response, m_controller, false, false);
f_res.setHeader(CmsRequestUtil.HEADER_CONTENT_TYPE, "application/borked");
assertTrue("non-top request does not set content type header", m_resMock.m_invocations.isEmpty());
f_res.setContentType("application/stillborked");
assertTrue("non-top request does not set content type header", m_resMock.m_invocations.isEmpty());
// test that top elements only set content type once
// first, try with a call to setContentType()
f_res = new CmsFlexResponse(m_response, m_controller, false, true);
f_res.setContentType("text/foo");
assertEquals("one method has been invoked on the actual response", 1, m_resMock.m_invocations.size());
List setCalls = m_resMock.getCalls(SET_CONTENT_TYPE);
assertEquals("top element has called setContentType() on the actual servlet response", 1, setCalls.size());
assertEquals("correct content type value passed", "text/foo", ((Object[])setCalls.get(0))[0]);
// subsequent attempts to set the content type on the same response should have no affect
f_res.setContentType("text/bar");
assertEquals("top element did NOT call content type method again", 1, setCalls.size());
f_res.setHeader(CmsRequestUtil.HEADER_CONTENT_TYPE, "text/baz");
assertEquals("still no more calls to setContentType() method", 1, setCalls.size());
assertEquals("no other methods called on request", 1, m_resMock.m_invocations.size());
// now, try with a call to setHeader on a new top response
f_res = new CmsFlexResponse(m_response, m_controller, false, true);
f_res.setHeader(CmsRequestUtil.HEADER_CONTENT_TYPE, "text/qux");
assertEquals("setContentType() was called from setHeader", 2, setCalls.size());
assertEquals("correct content type value passed", "text/qux", ((Object[])setCalls.get(1))[0]);
// subsequent attempts to set the content type on the same response should have no affect
f_res.setContentType("text/quux");
assertEquals("no further calls to setContentType", 2, setCalls.size());
assertEquals("no other methods called", 1, m_resMock.m_invocations.size());
f_res.setHeader(CmsRequestUtil.HEADER_CONTENT_TYPE, "text/arg");
assertEquals("no further calls to setContentType", 2, setCalls.size());
assertEquals("no other methods called", 1, m_resMock.m_invocations.size());
}
/**
* Initializes a flex cache controller and mock servlet request and response objects to be
* used by this unit tests.
*
* @throws Exception if the setup fails
*
* @see junit.framework.TestCase#setUp()
*/
@Override
protected void setUp() throws Exception {
super.setUp();
CmsObject cms = OpenCms.initCmsObject(OpenCms.getDefaultUsers().getUserGuest());
if (!OpenCms.getDefaultUsers().isUserGuest(cms.getRequestContext().getCurrentUser().getName())) {
fail("'Guest' user could not be properly initialized!");
}
m_reqMock = new RecordingMock(new RequestStub());
m_request = createMockRequest(m_reqMock);
m_resMock = new RecordingMock();
m_response = createMockResponse(m_resMock);
m_controller = new CmsFlexController(
cms,
null,
CmsFlexDummyLoader.getFlexCache(),
m_request,
m_response,
false,
true);
CmsFlexController.setController(m_request, m_controller);
}
/**
* @see junit.framework.TestCase#tearDown()
*/
@Override
protected void tearDown() throws Exception {
super.tearDown();
m_reqMock = null;
m_resMock = null;
m_request = null;
m_response = null;
m_controller = null;
}
}