You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by lu...@apache.org on 2022/11/27 08:24:58 UTC

[struts] 15/23: WW-5233 Copies Tiles Portal related tests

This is an automated email from the ASF dual-hosted git repository.

lukaszlenart pushed a commit to branch WW-5233-tiles
in repository https://gitbox.apache.org/repos/asf/struts.git

commit 55987963a933fe0faaf76a4329ec7ef17da50316
Author: Lukasz Lenart <lu...@apache.org>
AuthorDate: Mon Oct 3 08:52:41 2022 +0200

    WW-5233 Copies Tiles Portal related tests
---
 plugins/portlet-tiles/pom.xml                      |   5 +
 .../portlet/delegate/StateAwareParameterMap.java   | 112 ------
 .../delegate/StateAwareRequestDelegate.java        |  83 ----
 .../delegate/StateAwareResponseDelegate.java       |  57 ---
 .../extractor/StateAwareParameterExtractor.java    |   2 +-
 .../tiles/request/portlet/PortletRequestTest.java  | 424 +++++++++++++++++++++
 .../request/portlet/RenderPortletRequestTest.java  |  69 ++++
 .../portlet/delegate/MimeResponseDelegateTest.java | 132 +++++++
 .../delegate/PortletRequestDelegateTest.java       |  83 ++++
 .../extractor/ApplicationScopeExtractorTest.java   | 106 ++++++
 .../portlet/extractor/HeaderExtractorTest.java     | 117 ++++++
 .../extractor/InitParameterExtractorTest.java      |  83 ++++
 .../portlet/extractor/ParameterExtractorTest.java  |  83 ++++
 .../extractor/RequestScopeExtractorTest.java       | 107 ++++++
 .../extractor/SessionScopeExtractorTest.java       | 154 ++++++++
 .../StateAwareParameterExtractorTest.java}         |  37 +-
 .../request/collection/ReadOnlyEnumerationMap.java |   5 +-
 17 files changed, 1385 insertions(+), 274 deletions(-)

diff --git a/plugins/portlet-tiles/pom.xml b/plugins/portlet-tiles/pom.xml
index 3ce787962..1ea145562 100644
--- a/plugins/portlet-tiles/pom.xml
+++ b/plugins/portlet-tiles/pom.xml
@@ -50,6 +50,11 @@
             <artifactId>portlet-api</artifactId>
             <scope>provided</scope>
         </dependency>
+        <dependency>
+            <groupId>org.easymock</groupId>
+            <artifactId>easymock</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
     <properties>
     	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
diff --git a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/StateAwareParameterMap.java b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/StateAwareParameterMap.java
deleted file mode 100644
index 34e36bb31..000000000
--- a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/StateAwareParameterMap.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * $Id$
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tiles.request.portlet.delegate;
-
-import java.util.Collection;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Parameter map to be used when the response is a {@link javax.portlet.StateAwareResponse}.
- */
-public class StateAwareParameterMap implements Map<String, String[]> {
-
-    /**
-     * The request parameter map.
-     */
-    private final Map<String, String[]> requestMap;
-
-    /**
-     * The response parameter map.
-     */
-    private final Map<String, String[]> responseMap;
-
-    /**
-     * Constructor.
-     *
-     * @param requestMap The request parameter map.
-     * @param responseMap The response parameter map.
-     */
-    public StateAwareParameterMap(Map<String, String[]> requestMap, Map<String, String[]> responseMap) {
-        this.requestMap = requestMap;
-        this.responseMap = responseMap;
-    }
-
-    @Override
-    public void clear() {
-        responseMap.clear();
-    }
-
-    @Override
-    public boolean containsKey(Object key) {
-        return requestMap.containsKey(key);
-    }
-
-    @Override
-    public boolean containsValue(Object value) {
-        return requestMap.containsValue(value);
-    }
-
-    @Override
-    public Set<Entry<String, String[]>> entrySet() {
-        return requestMap.entrySet();
-    }
-
-    @Override
-    public String[] get(Object key) {
-        return requestMap.get(key);
-    }
-
-    @Override
-    public boolean isEmpty() {
-        return requestMap.isEmpty();
-    }
-
-    @Override
-    public Set<String> keySet() {
-        return requestMap.keySet();
-    }
-
-    @Override
-    public String[] put(String key, String[] value) {
-        return responseMap.put(key, value);
-    }
-
-    @Override
-    public void putAll(Map<? extends String, ? extends String[]> m) {
-        responseMap.putAll(m);
-    }
-
-    @Override
-    public String[] remove(Object key) {
-        return responseMap.remove(key);
-    }
-
-    @Override
-    public int size() {
-        return requestMap.size();
-    }
-
-    @Override
-    public Collection<String[]> values() {
-        return requestMap.values();
-    }
-}
diff --git a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/StateAwareRequestDelegate.java b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/StateAwareRequestDelegate.java
deleted file mode 100644
index ede98a745..000000000
--- a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/StateAwareRequestDelegate.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * $Id$
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tiles.request.portlet.delegate;
-
-import org.apache.tiles.request.collection.AddableParameterMap;
-import org.apache.tiles.request.portlet.extractor.StateAwareParameterExtractor;
-
-import javax.portlet.PortletRequest;
-import javax.portlet.StateAwareResponse;
-import java.util.Map;
-
-/**
- * Exposes parameters getting them from a portlet reques and allowing to be put into a {@link StateAwareResponse}.
- */
-public class StateAwareRequestDelegate implements RequestDelegate {
-
-    /**
-     * The request.
-     */
-    private final PortletRequest request;
-
-    /**
-     * The response.
-     */
-    private final StateAwareResponse response;
-
-    /**
-     * Constructor.
-     *
-     * @param request The request.
-     * @param response The response.
-     */
-    public StateAwareRequestDelegate(PortletRequest request, StateAwareResponse response) {
-        this.request = request;
-        this.response = response;
-    }
-
-    /**
-     * <p>The lazily instantiated <code>Map</code> of request
-     * parameter name-value.</p>
-     */
-    private Map<String, String> param = null;
-
-    /**
-     * <p>The lazily instantiated <code>Map</code> of request
-     * parameter name-values.</p>
-     */
-    private Map<String, String[]> paramValues = null;
-
-    /** {@inheritDoc} */
-    public Map<String, String> getParam() {
-        if ((param == null) && (request != null)) {
-            param = new AddableParameterMap(new StateAwareParameterExtractor(request, response));
-        }
-        return (param);
-    }
-
-    /** {@inheritDoc} */
-    public Map<String, String[]> getParamValues() {
-        if ((paramValues == null) && (request != null)) {
-            paramValues = new StateAwareParameterMap(request.getParameterMap(), response.getRenderParameterMap());
-        }
-        return (paramValues);
-    }
-}
diff --git a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/StateAwareResponseDelegate.java b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/StateAwareResponseDelegate.java
deleted file mode 100644
index 20e05cbcb..000000000
--- a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/StateAwareResponseDelegate.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * $Id$
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tiles.request.portlet.delegate;
-
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.io.Writer;
-
-/**
- * A state aware response does not allow to access to the output stream and similar, so it is, essentially,
- * a feature blocker.
- */
-public class StateAwareResponseDelegate implements ResponseDelegate {
-
-    @Override
-    public OutputStream getOutputStream() {
-        throw new UnsupportedOperationException("No outputstream available for state-aware response");
-    }
-
-    @Override
-    public PrintWriter getPrintWriter() {
-        throw new UnsupportedOperationException("No outputstream available for state-aware response");
-    }
-
-    @Override
-    public Writer getWriter() {
-        throw new UnsupportedOperationException("No outputstream available for state-aware response");
-    }
-
-    @Override
-    public boolean isResponseCommitted() {
-        return false;
-    }
-
-    @Override
-    public void setContentType(String contentType) {
-        throw new UnsupportedOperationException("No outputstream available for state-aware response");
-    }
-}
diff --git a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/StateAwareParameterExtractor.java b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/StateAwareParameterExtractor.java
index 3b18b7343..a14f53a7b 100644
--- a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/StateAwareParameterExtractor.java
+++ b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/StateAwareParameterExtractor.java
@@ -33,7 +33,7 @@ public class StateAwareParameterExtractor extends ParameterExtractor implements
     /**
      * The portlet response.
      */
-    private StateAwareResponse response;
+    private final StateAwareResponse response;
 
     /**
      * Constructor.
diff --git a/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/PortletRequestTest.java b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/PortletRequestTest.java
new file mode 100644
index 000000000..53a6bf856
--- /dev/null
+++ b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/PortletRequestTest.java
@@ -0,0 +1,424 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tiles.request.portlet;
+
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.collection.HeaderValuesMap;
+import org.apache.tiles.request.collection.ReadOnlyEnumerationMap;
+import org.apache.tiles.request.collection.ScopeMap;
+import org.apache.tiles.request.portlet.delegate.RequestDelegate;
+import org.apache.tiles.request.portlet.delegate.ResponseDelegate;
+import org.apache.tiles.request.portlet.extractor.HeaderExtractor;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.portlet.PortletContext;
+import javax.portlet.PortletException;
+import javax.portlet.PortletRequestDispatcher;
+import javax.portlet.PortletResponse;
+import javax.servlet.ServletOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Locale;
+import java.util.Map;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Tests {@link PortletRequest}.
+ */
+public class PortletRequestTest {
+
+    /**
+     * The application context.
+     */
+    private ApplicationContext applicationContext;
+
+    /**
+     * The portlet context.
+     */
+    private PortletContext portletContext;
+
+    /**
+     * The request.
+     */
+    private javax.portlet.PortletRequest request;
+
+    /**
+     * The response.
+     */
+    private PortletResponse response;
+
+    /**
+     * The request to test.
+     */
+    private PortletRequest req;
+
+    /**
+     * The request delegate.
+     */
+    private RequestDelegate requestDelegate;
+
+    /**
+     * The response delegate.
+     */
+    private ResponseDelegate responseDelegate;
+
+    /**
+     * Sets up the test.
+     */
+    @Before
+    public void setUp() {
+        applicationContext = createMock(ApplicationContext.class);
+        portletContext = createMock(PortletContext.class);
+        request = createMock(javax.portlet.PortletRequest.class);
+        response = createMock(PortletResponse.class);
+        requestDelegate = createMock(RequestDelegate.class);
+        responseDelegate = createMock(ResponseDelegate.class);
+        req = new PortletRequest(applicationContext, portletContext, request,
+            response, requestDelegate, responseDelegate);
+    }
+
+    /**
+     * Test method for {@link PortletRequest#doForward(String)}.
+     *
+     * @throws IOException      If something goes wrong.
+     * @throws PortletException If something goes wrong.
+     */
+    @Test
+    public void testDoForward() throws PortletException, IOException {
+        PortletRequestDispatcher rd = createMock(PortletRequestDispatcher.class);
+
+        expect(responseDelegate.isResponseCommitted()).andReturn(false);
+        expect(portletContext.getRequestDispatcher("/my/path")).andReturn(rd);
+        rd.forward(request, response);
+
+        replay(applicationContext, portletContext, request, response, rd);
+        req.doForward("/my/path");
+        verify(applicationContext, portletContext, request, response, rd);
+    }
+
+    /**
+     * Test method for {@link PortletRequest#doForward(String)}.
+     *
+     * @throws IOException If something goes wrong.
+     */
+    @Test(expected = IOException.class)
+    public void testDoForwardNoDispatcher() throws IOException {
+        expect(responseDelegate.isResponseCommitted()).andReturn(false);
+        expect(portletContext.getRequestDispatcher("/my/path")).andReturn(null);
+
+        replay(applicationContext, request, response, portletContext, requestDelegate, responseDelegate);
+        try {
+            req.doForward("/my/path");
+        } finally {
+            verify(applicationContext, request, response, portletContext, requestDelegate, responseDelegate);
+        }
+    }
+
+    /**
+     * Test method for {@link PortletRequest#doForward(String)}.
+     *
+     * @throws IOException      If something goes wrong.
+     * @throws PortletException If something goes wrong.
+     */
+    @Test(expected = IOException.class)
+    public void testDoForwardPortletException() throws PortletException, IOException {
+        PortletRequestDispatcher rd = createMock(PortletRequestDispatcher.class);
+
+        expect(responseDelegate.isResponseCommitted()).andReturn(false);
+        expect(portletContext.getRequestDispatcher("/my/path")).andReturn(rd);
+        rd.forward(request, response);
+        expectLastCall().andThrow(new PortletException());
+
+        replay(applicationContext, request, response, rd, portletContext, requestDelegate, responseDelegate);
+        try {
+            req.doForward("/my/path");
+        } finally {
+            verify(applicationContext, request, response, rd, portletContext, requestDelegate, responseDelegate);
+        }
+    }
+
+    /**
+     * Test method for {@link PortletRequest#doForward(String)}.
+     *
+     * @throws IOException      If something goes wrong.
+     * @throws PortletException If something goes wrong.
+     */
+    @Test
+    public void testDoForwardInclude() throws PortletException, IOException {
+        PortletRequestDispatcher rd = createMock(PortletRequestDispatcher.class);
+
+        expect(responseDelegate.isResponseCommitted()).andReturn(true);
+        expect(portletContext.getRequestDispatcher("/my/path")).andReturn(rd);
+        rd.include(request, response);
+
+        replay(applicationContext, request, response, rd, portletContext, requestDelegate, responseDelegate);
+        req.doForward("/my/path");
+        verify(applicationContext, request, response, rd, portletContext, requestDelegate, responseDelegate);
+    }
+
+    /**
+     * Test method for {@link PortletRequest#doInclude(String)}.
+     *
+     * @throws IOException      If something goes wrong.
+     * @throws PortletException If something goes wrong.
+     */
+    @Test
+    public void testDoInclude() throws IOException, PortletException {
+        PortletRequestDispatcher rd = createMock(PortletRequestDispatcher.class);
+
+        expect(portletContext.getRequestDispatcher("/my/path")).andReturn(rd);
+        rd.include(request, response);
+
+        replay(applicationContext, request, response, rd, portletContext, requestDelegate, responseDelegate);
+        req.doInclude("/my/path");
+        verify(applicationContext, request, response, rd, portletContext, requestDelegate, responseDelegate);
+    }
+
+    /**
+     * Test method for {@link PortletRequest#doInclude(String)}.
+     *
+     * @throws IOException If something goes wrong.
+     */
+    @Test(expected = IOException.class)
+    public void testDoIncludeNoDispatcher() throws IOException {
+        expect(portletContext.getRequestDispatcher("/my/path")).andReturn(null);
+
+        replay(applicationContext, request, response, portletContext, requestDelegate, responseDelegate);
+        try {
+            req.doInclude("/my/path");
+        } finally {
+            verify(applicationContext, request, response, portletContext, requestDelegate, responseDelegate);
+        }
+    }
+
+    /**
+     * Test method for {@link PortletRequest#doInclude(String)}.
+     *
+     * @throws IOException      If something goes wrong.
+     * @throws PortletException If something goes wrong.
+     */
+    @Test(expected = IOException.class)
+    public void testDoIncludePortletException() throws IOException, PortletException {
+        PortletRequestDispatcher rd = createMock(PortletRequestDispatcher.class);
+
+        expect(portletContext.getRequestDispatcher("/my/path")).andReturn(rd);
+        rd.include(request, response);
+        expectLastCall().andThrow(new PortletException());
+
+        replay(applicationContext, request, response, rd, portletContext, requestDelegate, responseDelegate);
+        try {
+            req.doInclude("/my/path");
+        } finally {
+            verify(applicationContext, request, response, rd, portletContext, requestDelegate, responseDelegate);
+        }
+    }
+
+    /**
+     * Test method for {@link PortletRequest#getHeader()}.
+     */
+    @Test
+    public void testGetHeader() {
+        assertTrue(req.getHeader() instanceof ReadOnlyEnumerationMap);
+    }
+
+    /**
+     * Test method for {@link PortletRequest#getResponseHeaders()}.
+     */
+    @Test
+    public void testGetResponseHeaders() {
+        assertTrue(req.getResponseHeaders() instanceof HeaderExtractor);
+    }
+
+    /**
+     * Test method for {@link PortletRequest#getHeaderValues()}.
+     */
+    @Test
+    public void testGetHeaderValues() {
+        assertTrue(req.getHeaderValues() instanceof HeaderValuesMap);
+    }
+
+    /**
+     * Test method for {@link PortletRequest#getParam()}.
+     */
+    @Test
+    public void testGetParam() {
+        Map<String, String> map = createMock(Map.class);
+
+        expect(requestDelegate.getParam()).andReturn(map);
+
+        replay(applicationContext, request, response, portletContext, requestDelegate, responseDelegate);
+        assertEquals(map, req.getParam());
+        verify(applicationContext, request, response, portletContext, requestDelegate, responseDelegate);
+    }
+
+    /**
+     * Test method for {@link PortletRequest#getParamValues()}.
+     */
+    @Test
+    public void testGetParamValues() {
+        Map<String, String[]> paramMap = createMock(Map.class);
+
+        expect(requestDelegate.getParamValues()).andReturn(paramMap);
+
+        replay(applicationContext, request, response, paramMap, portletContext, requestDelegate, responseDelegate);
+        assertEquals(paramMap, req.getParamValues());
+        verify(applicationContext, request, response, paramMap, portletContext, requestDelegate, responseDelegate);
+    }
+
+    /**
+     * Test method for {@link PortletRequest#getRequestScope()}.
+     */
+    @Test
+    public void testGetRequestScope() {
+        assertTrue(req.getRequestScope() instanceof ScopeMap);
+    }
+
+    /**
+     * Test method for {@link PortletRequest#getSessionScope()}.
+     */
+    @Test
+    public void testGetSessionScope() {
+        assertTrue(req.getSessionScope() instanceof ScopeMap);
+    }
+
+    /**
+     * Test method for {@link PortletRequest#getPortletSessionScope()}.
+     */
+    @Test
+    public void testGetPortletSessionScope() {
+        assertTrue(req.getPortletSessionScope() instanceof ScopeMap);
+    }
+
+    /**
+     * Test method for {@link PortletRequest#getOutputStream()}.
+     *
+     * @throws IOException If something goes wrong.
+     */
+    @Test
+    public void testGetOutputStream() throws IOException {
+        ServletOutputStream os = createMock(ServletOutputStream.class);
+
+        expect(responseDelegate.getOutputStream()).andReturn(os);
+
+        replay(applicationContext, request, response, os, portletContext, requestDelegate, responseDelegate);
+        assertEquals(req.getOutputStream(), os);
+        verify(applicationContext, request, response, os, portletContext, requestDelegate, responseDelegate);
+    }
+
+    /**
+     * Test method for {@link PortletRequest#getWriter()}.
+     *
+     * @throws IOException If something goes wrong.
+     */
+    @Test
+    public void testGetWriter() throws IOException {
+        PrintWriter os = createMock(PrintWriter.class);
+
+        expect(responseDelegate.getWriter()).andReturn(os);
+
+        replay(applicationContext, request, response, os, portletContext, requestDelegate, responseDelegate);
+        assertEquals(req.getWriter(), os);
+        verify(applicationContext, request, response, os, portletContext, requestDelegate, responseDelegate);
+    }
+
+    /**
+     * Test method for {@link PortletRequest#getPrintWriter()}.
+     *
+     * @throws IOException If something goes wrong.
+     */
+    @Test
+    public void testGetPrintWriter() throws IOException {
+        PrintWriter os = createMock(PrintWriter.class);
+
+        expect(responseDelegate.getPrintWriter()).andReturn(os);
+
+        replay(applicationContext, request, response, os, portletContext, requestDelegate, responseDelegate);
+        assertEquals(req.getPrintWriter(), os);
+        verify(applicationContext, request, response, os, portletContext, requestDelegate, responseDelegate);
+    }
+
+    /**
+     * Test method for {@link PortletRequest#isResponseCommitted()}.
+     */
+    @Test
+    public void testIsResponseCommitted() {
+        expect(responseDelegate.isResponseCommitted()).andReturn(true);
+
+        replay(applicationContext, request, response, portletContext, requestDelegate, responseDelegate);
+        assertTrue(req.isResponseCommitted());
+        verify(applicationContext, request, response, portletContext, requestDelegate, responseDelegate);
+    }
+
+    /**
+     * Test method for {@link PortletRequest#setContentType(String)}.
+     */
+    @Test
+    public void testSetContentType() {
+        responseDelegate.setContentType("text/html");
+
+        replay(applicationContext, request, response, portletContext, requestDelegate, responseDelegate);
+        req.setContentType("text/html");
+        verify(applicationContext, request, response, portletContext, requestDelegate, responseDelegate);
+    }
+
+    /**
+     * Test method for {@link PortletRequest#getRequestLocale()}.
+     */
+    @Test
+    public void testGetRequestLocale() {
+        Locale locale = Locale.ITALY;
+
+        expect(request.getLocale()).andReturn(locale);
+
+        replay(applicationContext, request, response, portletContext, requestDelegate, responseDelegate);
+        assertEquals(locale, req.getRequestLocale());
+        verify(applicationContext, request, response, portletContext, requestDelegate, responseDelegate);
+    }
+
+    /**
+     * Test method for {@link PortletRequest#getRequest()}.
+     */
+    @Test
+    public void testGetRequest() {
+        replay(applicationContext, request, response, portletContext, requestDelegate, responseDelegate);
+        assertEquals(request, req.getRequest());
+        verify(applicationContext, request, response, portletContext, requestDelegate, responseDelegate);
+    }
+
+    /**
+     * Test method for {@link PortletRequest#isUserInRole(String)}.
+     */
+    @Test
+    public void testIsUserInRole() {
+        expect(request.isUserInRole("myrole")).andReturn(true);
+
+        replay(applicationContext, request, response, portletContext, requestDelegate, responseDelegate);
+        assertTrue(req.isUserInRole("myrole"));
+        verify(applicationContext, request, response, portletContext, requestDelegate, responseDelegate);
+    }
+
+}
diff --git a/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/RenderPortletRequestTest.java b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/RenderPortletRequestTest.java
new file mode 100644
index 000000000..5bba700fb
--- /dev/null
+++ b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/RenderPortletRequestTest.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tiles.request.portlet;
+
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.portlet.delegate.MimeResponseDelegate;
+import org.apache.tiles.request.portlet.delegate.PortletRequestDelegate;
+import org.junit.Test;
+
+import javax.portlet.PortletContext;
+import javax.portlet.RenderRequest;
+import javax.portlet.RenderResponse;
+import java.lang.reflect.Field;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Tests {@link RenderPortletRequest}.
+ */
+public class RenderPortletRequestTest {
+
+    /**
+     * Test method for
+     * {@link RenderPortletRequest#RenderPortletRequest(ApplicationContext, PortletContext,
+     * RenderRequest, RenderResponse)}.
+     *
+     * @throws NoSuchFieldException     If something goes wrong.
+     * @throws SecurityException        If something goes wrong.
+     * @throws IllegalAccessException   If something goes wrong.
+     * @throws IllegalArgumentException If something goes wrong.
+     */
+    @Test
+    public void testRenderPortletRequest() throws NoSuchFieldException, IllegalAccessException {
+        ApplicationContext applicationContext = createMock(ApplicationContext.class);
+        PortletContext portletContext = createMock(PortletContext.class);
+        RenderRequest request = createMock(RenderRequest.class);
+        RenderResponse response = createMock(RenderResponse.class);
+
+        replay(applicationContext, portletContext, request, response);
+        RenderPortletRequest req = new RenderPortletRequest(applicationContext,
+            portletContext, request, response);
+        Class<? extends RenderPortletRequest> clazz = req.getClass();
+        Field field = clazz.getSuperclass().getDeclaredField("requestDelegate");
+        assertTrue(field.get(req) instanceof PortletRequestDelegate);
+        field = clazz.getSuperclass().getDeclaredField("responseDelegate");
+        assertTrue(field.get(req) instanceof MimeResponseDelegate);
+        verify(applicationContext, portletContext, request, response);
+    }
+
+}
diff --git a/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/delegate/MimeResponseDelegateTest.java b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/delegate/MimeResponseDelegateTest.java
new file mode 100644
index 000000000..25d653456
--- /dev/null
+++ b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/delegate/MimeResponseDelegateTest.java
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tiles.request.portlet.delegate;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.portlet.MimeResponse;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Tests {@link MimeResponseDelegate}.
+ */
+public class MimeResponseDelegateTest {
+
+    /**
+     * The response.
+     */
+    private MimeResponse response;
+
+    /**
+     * The delegate to test.
+     */
+    private MimeResponseDelegate delegate;
+
+    /**
+     * Sets up the test.
+     */
+    @Before
+    public void setUp() {
+        response = createMock(MimeResponse.class);
+        delegate = new MimeResponseDelegate(response);
+    }
+
+    /**
+     * Test method for {@link MimeResponseDelegate#getOutputStream()}.
+     *
+     * @throws IOException If something goes wrong.
+     */
+    @Test
+    public void testGetOutputStream() throws IOException {
+        OutputStream os = createMock(OutputStream.class);
+
+        expect(response.getPortletOutputStream()).andReturn(os);
+
+        replay(response, os);
+        assertEquals(os, delegate.getOutputStream());
+        verify(response, os);
+    }
+
+    /**
+     * Test method for {@link MimeResponseDelegate#getPrintWriter()}.
+     *
+     * @throws IOException If something goes wrong.
+     */
+    @Test
+    public void testGetPrintWriter() throws IOException {
+        PrintWriter os = createMock(PrintWriter.class);
+
+        expect(response.getWriter()).andReturn(os);
+
+        replay(response, os);
+        assertEquals(os, delegate.getPrintWriter());
+        verify(response, os);
+    }
+
+    /**
+     * Test method for {@link MimeResponseDelegate#getWriter()}.
+     *
+     * @throws IOException If something goes wrong.
+     */
+    @Test
+    public void testGetWriter() throws IOException {
+        PrintWriter os = createMock(PrintWriter.class);
+
+        expect(response.getWriter()).andReturn(os);
+
+        replay(response, os);
+        assertEquals(os, delegate.getWriter());
+        verify(response, os);
+    }
+
+    /**
+     * Test method for {@link MimeResponseDelegate#isResponseCommitted()}.
+     */
+    @Test
+    public void testIsResponseCommitted() {
+        expect(response.isCommitted()).andReturn(true);
+
+        replay(response);
+        assertTrue(delegate.isResponseCommitted());
+        verify(response);
+    }
+
+    /**
+     * Test method for {@link MimeResponseDelegate#setContentType(String)}.
+     */
+    @Test
+    public void testSetContentType() {
+        response.setContentType("text/html");
+
+        replay(response);
+        delegate.setContentType("text/html");
+        verify(response);
+    }
+
+}
diff --git a/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/delegate/PortletRequestDelegateTest.java b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/delegate/PortletRequestDelegateTest.java
new file mode 100644
index 000000000..ce6d4e849
--- /dev/null
+++ b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/delegate/PortletRequestDelegateTest.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tiles.request.portlet.delegate;
+
+import org.apache.tiles.request.collection.ReadOnlyEnumerationMap;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.portlet.PortletRequest;
+import java.util.Map;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Tests {@link PortletRequestDelegate}.
+ */
+public class PortletRequestDelegateTest {
+
+    /**
+     * The request.
+     */
+    private PortletRequest request;
+
+    /**
+     * The delegate to test.
+     */
+    private PortletRequestDelegate delegate;
+
+    /**
+     * Sets up the test.
+     */
+    @Before
+    public void setUp() {
+        request = createMock(PortletRequest.class);
+        delegate = new PortletRequestDelegate(request);
+    }
+
+    /**
+     * Test method for {@link PortletRequestDelegate#getParam()}.
+     */
+    @Test
+    public void testGetParam() {
+        replay(request);
+        assertTrue(delegate.getParam() instanceof ReadOnlyEnumerationMap);
+        verify(request);
+    }
+
+    /**
+     * Test method for {@link PortletRequestDelegate#getParamValues()}.
+     */
+    @Test
+    public void testGetParamValues() {
+        Map<String, String[]> params = createMock(Map.class);
+
+        expect(request.getParameterMap()).andReturn(params);
+
+        replay(request, params);
+        assertEquals(params, delegate.getParamValues());
+        verify(request, params);
+    }
+
+}
diff --git a/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/ApplicationScopeExtractorTest.java b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/ApplicationScopeExtractorTest.java
new file mode 100644
index 000000000..5ede84f69
--- /dev/null
+++ b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/ApplicationScopeExtractorTest.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tiles.request.portlet.extractor;
+
+import org.apache.tiles.request.portlet.extractor.ApplicationScopeExtractor;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.portlet.PortletContext;
+import java.util.Enumeration;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests {@link ApplicationScopeExtractor}.
+ */
+public class ApplicationScopeExtractorTest {
+
+    /**
+     * The portlet context.
+     */
+    private PortletContext context;
+
+    /**
+     * The extractot to test.
+     */
+    private ApplicationScopeExtractor extractor;
+
+    /**
+     * Sets up the test.
+     */
+    @Before
+    public void setUp() {
+        context = createMock(PortletContext.class);
+        extractor = new ApplicationScopeExtractor(context);
+    }
+
+    /**
+     * Test method for {@link ApplicationScopeExtractor#setValue(String, Object)}.
+     */
+    @Test
+    public void testSetValue() {
+        context.setAttribute("attribute", "value");
+
+        replay(context);
+        extractor.setValue("attribute", "value");
+        verify(context);
+    }
+
+    /**
+     * Test method for {@link ApplicationScopeExtractor#removeValue(String)}.
+     */
+    @Test
+    public void testRemoveValue() {
+        context.removeAttribute("attribute");
+
+        replay(context);
+        extractor.removeValue("attribute");
+        verify(context);
+    }
+
+    /**
+     * Test method for {@link ApplicationScopeExtractor#getKeys()}.
+     */
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testGetKeys() {
+        Enumeration<String> keys = createMock(Enumeration.class);
+        expect(context.getAttributeNames()).andReturn(keys);
+
+        replay(context, keys);
+        assertEquals(keys, extractor.getKeys());
+        verify(context, keys);
+    }
+
+    /**
+     * Test method for {@link ApplicationScopeExtractor#getValue(String)}.
+     */
+    @Test
+    public void testGetValue() {
+        expect(context.getAttribute("attribute")).andReturn("value");
+
+        replay(context);
+        assertEquals("value", extractor.getValue("attribute"));
+        verify(context);
+    }
+
+}
diff --git a/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/HeaderExtractorTest.java b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/HeaderExtractorTest.java
new file mode 100644
index 000000000..7f5054c02
--- /dev/null
+++ b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/HeaderExtractorTest.java
@@ -0,0 +1,117 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tiles.request.portlet.extractor;
+
+import org.apache.tiles.request.portlet.extractor.HeaderExtractor;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.portlet.PortletRequest;
+import javax.portlet.PortletResponse;
+import java.util.Enumeration;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests {@link HeaderExtractor}.
+ */
+public class HeaderExtractorTest {
+
+    /**
+     * The request.
+     */
+    private PortletRequest request;
+
+    /**
+     * The response.
+     */
+    private PortletResponse response;
+
+    /**
+     * The extractor to test.
+     */
+    private HeaderExtractor extractor;
+
+    /**
+     * Sets up the test.
+     */
+    @Before
+    public void setUp() {
+        request = createMock(PortletRequest.class);
+        response = createMock(PortletResponse.class);
+        extractor = new HeaderExtractor(request, response);
+    }
+
+    /**
+     * Test method for {@link HeaderExtractor#getKeys()}.
+     */
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testGetKeys() {
+        Enumeration<String> keys = createMock(Enumeration.class);
+
+        expect(request.getPropertyNames()).andReturn(keys);
+
+        replay(request, response, keys);
+        assertEquals(keys, extractor.getKeys());
+        verify(request, response, keys);
+    }
+
+    /**
+     * Test method for {@link HeaderExtractor#getValue(String)}.
+     */
+    @Test
+    public void testGetValue() {
+        expect(request.getProperty("name")).andReturn("value");
+
+        replay(request, response);
+        assertEquals("value", extractor.getValue("name"));
+        verify(request, response);
+    }
+
+    /**
+     * Test method for {@link HeaderExtractor#getValues(String)}.
+     */
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testGetValues() {
+        Enumeration<String> keys = createMock(Enumeration.class);
+
+        expect(request.getProperties("name")).andReturn(keys);
+
+        replay(request, response, keys);
+        assertEquals(keys, extractor.getValues("name"));
+        verify(request, response, keys);
+    }
+
+    /**
+     * Test method for {@link HeaderExtractor#setValue(String, String)}.
+     */
+    @Test
+    public void testSetValue() {
+        response.setProperty("name", "value");
+
+        replay(request, response);
+        extractor.setValue("name", "value");
+        verify(request, response);
+    }
+
+}
diff --git a/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/InitParameterExtractorTest.java b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/InitParameterExtractorTest.java
new file mode 100644
index 000000000..66a1f9ea7
--- /dev/null
+++ b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/InitParameterExtractorTest.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tiles.request.portlet.extractor;
+
+import org.apache.tiles.request.portlet.extractor.InitParameterExtractor;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.portlet.PortletContext;
+import java.util.Enumeration;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests {@link InitParameterExtractor}.
+ */
+public class InitParameterExtractorTest {
+
+    /**
+     * The portlet context.
+     */
+    private PortletContext context;
+
+    /**
+     * The extractor to test.
+     */
+    private InitParameterExtractor extractor;
+
+    /**
+     * Sets up the test.
+     */
+    @Before
+    public void setUp() {
+        context = createMock(PortletContext.class);
+        extractor = new InitParameterExtractor(context);
+    }
+
+    /**
+     * Test method for {@link InitParameterExtractor#getKeys()}.
+     */
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testGetKeys() {
+        Enumeration<String> keys = createMock(Enumeration.class);
+
+        expect(context.getInitParameterNames()).andReturn(keys);
+
+        replay(context, keys);
+        assertEquals(keys, extractor.getKeys());
+        verify(context, keys);
+    }
+
+    /**
+     * Test method for {@link InitParameterExtractor#getValue(String)}.
+     */
+    @Test
+    public void testGetValue() {
+        expect(context.getInitParameter("name")).andReturn("value");
+
+        replay(context);
+        assertEquals("value", extractor.getValue("name"));
+        verify(context);
+    }
+
+}
diff --git a/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/ParameterExtractorTest.java b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/ParameterExtractorTest.java
new file mode 100644
index 000000000..0e8005325
--- /dev/null
+++ b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/ParameterExtractorTest.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tiles.request.portlet.extractor;
+
+import org.apache.tiles.request.portlet.extractor.ParameterExtractor;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.portlet.PortletRequest;
+import java.util.Enumeration;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests {@link ParameterExtractor}.
+ */
+public class ParameterExtractorTest {
+
+    /**
+     * The request.
+     */
+    private PortletRequest request;
+
+    /**
+     * The extractor to test.
+     */
+    private ParameterExtractor extractor;
+
+    /**
+     * Sets up the test.
+     */
+    @Before
+    public void setUp() {
+        request = createMock(PortletRequest.class);
+        extractor = new ParameterExtractor(request);
+    }
+
+    /**
+     * Test method for {@link ParameterExtractor#getKeys()}.
+     */
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testGetKeys() {
+        Enumeration<String> keys = createMock(Enumeration.class);
+
+        expect(request.getParameterNames()).andReturn(keys);
+
+        replay(request, keys);
+        assertEquals(keys, extractor.getKeys());
+        verify(request, keys);
+    }
+
+    /**
+     * Test method for {@link ParameterExtractor#getValue(String)}.
+     */
+    @Test
+    public void testGetValue() {
+        expect(request.getParameter("name")).andReturn("value");
+
+        replay(request);
+        assertEquals("value", extractor.getValue("name"));
+        verify(request);
+    }
+
+}
diff --git a/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/RequestScopeExtractorTest.java b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/RequestScopeExtractorTest.java
new file mode 100644
index 000000000..df76a515e
--- /dev/null
+++ b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/RequestScopeExtractorTest.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tiles.request.portlet.extractor;
+
+import org.apache.tiles.request.portlet.extractor.RequestScopeExtractor;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.portlet.PortletRequest;
+import java.util.Enumeration;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests {@link RequestScopeExtractor}.
+ */
+public class RequestScopeExtractorTest {
+
+    /**
+     * The request to test.
+     */
+    private PortletRequest request;
+
+    /**
+     * The extractor to test.
+     */
+    private RequestScopeExtractor extractor;
+
+    /**
+     * Sets up the test.
+     */
+    @Before
+    public void setUp() {
+        request = createMock(PortletRequest.class);
+        extractor = new RequestScopeExtractor(request);
+    }
+
+    /**
+     * Test method for {@link RequestScopeExtractor#setValue(String, Object)}.
+     */
+    @Test
+    public void testSetValue() {
+        request.setAttribute("name", "value");
+
+        replay(request);
+        extractor.setValue("name", "value");
+        verify(request);
+    }
+
+    /**
+     * Test method for {@link RequestScopeExtractor#removeValue(String)}.
+     */
+    @Test
+    public void testRemoveValue() {
+        request.removeAttribute("name");
+
+        replay(request);
+        extractor.removeValue("name");
+        verify(request);
+    }
+
+    /**
+     * Test method for {@link RequestScopeExtractor#getKeys()}.
+     */
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testGetKeys() {
+        Enumeration<String> keys = createMock(Enumeration.class);
+
+        expect(request.getAttributeNames()).andReturn(keys);
+
+        replay(request, keys);
+        assertEquals(keys, extractor.getKeys());
+        verify(request, keys);
+    }
+
+    /**
+     * Test method for {@link RequestScopeExtractor#getValue(String)}.
+     */
+    @Test
+    public void testGetValue() {
+        expect(request.getAttribute("name")).andReturn("value");
+
+        replay(request);
+        assertEquals("value", extractor.getValue("name"));
+        verify(request);
+    }
+
+}
diff --git a/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/SessionScopeExtractorTest.java b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/SessionScopeExtractorTest.java
new file mode 100644
index 000000000..09010ff0c
--- /dev/null
+++ b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/SessionScopeExtractorTest.java
@@ -0,0 +1,154 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tiles.request.portlet.extractor;
+
+import org.apache.tiles.request.portlet.extractor.SessionScopeExtractor;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.portlet.PortletRequest;
+import javax.portlet.PortletSession;
+import java.util.Enumeration;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+/**
+ * Tests {@link SessionScopeExtractor}.
+ */
+public class SessionScopeExtractorTest {
+
+    /**
+     * The request.
+     */
+    private PortletRequest request;
+
+    /**
+     * The session.
+     */
+    private PortletSession session;
+
+    /**
+     * The scope to test.
+     */
+    private SessionScopeExtractor extractor;
+
+    /**
+     * Sets up the test.
+     */
+    @Before
+    public void setUp() {
+        request = createMock(PortletRequest.class);
+        session = createMock(PortletSession.class);
+        extractor = new SessionScopeExtractor(request, PortletSession.PORTLET_SCOPE);
+    }
+
+
+    /**
+     * Tests {@link SessionScopeExtractor#SessionScopeExtractor(PortletRequest, int)}.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testIllegalScope() {
+        replay(request, session);
+        new SessionScopeExtractor(request, 0);
+        verify(request, session);
+    }
+
+    /**
+     * Test method for {@link SessionScopeExtractor#setValue(String, Object)}.
+     */
+    @Test
+    public void testSetValue() {
+        expect(request.getPortletSession()).andReturn(session);
+        session.setAttribute("name", "value", PortletSession.PORTLET_SCOPE);
+
+        replay(request, session);
+        extractor.setValue("name", "value");
+        verify(request, session);
+    }
+
+    /**
+     * Test method for {@link SessionScopeExtractor#removeValue(String)}.
+     */
+    @Test
+    public void testRemoveValue() {
+        expect(request.getPortletSession(false)).andReturn(session);
+        session.removeAttribute("name", PortletSession.PORTLET_SCOPE);
+
+        replay(request, session);
+        extractor.removeValue("name");
+        verify(request, session);
+    }
+
+    /**
+     * Test method for {@link SessionScopeExtractor#getKeys()}.
+     */
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testGetKeys() {
+        Enumeration<String> keys = createMock(Enumeration.class);
+
+        expect(request.getPortletSession(false)).andReturn(session);
+        expect(session.getAttributeNames(PortletSession.PORTLET_SCOPE)).andReturn(keys);
+
+        replay(request, session, keys);
+        assertEquals(keys, extractor.getKeys());
+        verify(request, session, keys);
+    }
+
+    /**
+     * Test method for {@link SessionScopeExtractor#getKeys()}.
+     */
+    @Test
+    public void testGetKeysNoSession() {
+        expect(request.getPortletSession(false)).andReturn(null);
+
+        replay(request, session);
+        assertNull(extractor.getKeys());
+        verify(request, session);
+    }
+
+    /**
+     * Test method for {@link SessionScopeExtractor#getValue(String)}.
+     */
+    @Test
+    public void testGetValue() {
+        expect(request.getPortletSession(false)).andReturn(session);
+        expect(session.getAttribute("name", PortletSession.PORTLET_SCOPE)).andReturn("value");
+
+        replay(request, session);
+        assertEquals("value", extractor.getValue("name"));
+        verify(request, session);
+    }
+
+    /**
+     * Test method for {@link SessionScopeExtractor#getValue(String)}.
+     */
+    @Test
+    public void testGetValueNoSession() {
+        expect(request.getPortletSession(false)).andReturn(null);
+
+        replay(request, session);
+        assertNull(extractor.getValue("name"));
+        verify(request, session);
+    }
+
+}
diff --git a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/StateAwareParameterExtractor.java b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/StateAwareParameterExtractorTest.java
similarity index 55%
copy from plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/StateAwareParameterExtractor.java
copy to plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/StateAwareParameterExtractorTest.java
index 3b18b7343..5157b6fe6 100644
--- a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/StateAwareParameterExtractor.java
+++ b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/StateAwareParameterExtractorTest.java
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
  * distributed with this work for additional information
@@ -20,34 +18,33 @@
  */
 package org.apache.tiles.request.portlet.extractor;
 
-import org.apache.tiles.request.attribute.HasAddableKeys;
+import org.apache.tiles.request.portlet.extractor.StateAwareParameterExtractor;
+import org.junit.Test;
 
 import javax.portlet.PortletRequest;
 import javax.portlet.StateAwareResponse;
 
+import static org.easymock.EasyMock.*;
+
 /**
- * Extracts parameters from a request and allows putting render parameters in a state aware response.
+ * Tests {@link StateAwareParameterExtractor}.
  */
-public class StateAwareParameterExtractor extends ParameterExtractor implements HasAddableKeys<String> {
+public class StateAwareParameterExtractorTest {
 
     /**
-     * The portlet response.
+     * Test method for {@link StateAwareParameterExtractor#setValue(String, String)}.
      */
-    private StateAwareResponse response;
+    @Test
+    public void testSetValue() {
+        PortletRequest request = createMock(PortletRequest.class);
+        StateAwareResponse response = createMock(StateAwareResponse.class);
 
-    /**
-     * Constructor.
-     *
-     * @param request The portlet request.
-     * @param response The portlet response.
-     */
-    public StateAwareParameterExtractor(PortletRequest request, StateAwareResponse response) {
-        super(request);
-        this.response = response;
-    }
+        response.setRenderParameter("name", "value");
 
-    @Override
-    public void setValue(String key, String value) {
-        response.setRenderParameter(key, value);
+        replay(request, response);
+        StateAwareParameterExtractor extractor = new StateAwareParameterExtractor(request, response);
+        extractor.setValue("name", "value");
+        verify(request, response);
     }
+
 }
diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMap.java b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMap.java
index 2db0e83ae..d5cc16978 100644
--- a/plugins/tiles/src/main/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMap.java
+++ b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMap.java
@@ -322,7 +322,10 @@ public class ReadOnlyEnumerationMap<V> implements Map<String, V> {
 
             @Override
             public Entry<String, V> next() {
-                return extractNextEntry(namesEnumeration);
+                if (namesEnumeration.hasMoreElements()) {
+                    return extractNextEntry(namesEnumeration);
+                }
+                throw new NoSuchElementException();
             }
 
             @Override