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:50 UTC

[struts] 07/23: WW-5233 Copies Tiles Template 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 1d36a148b7bab12fe2ceb1c67a611d4282454027
Author: Lukasz Lenart <lu...@apache.org>
AuthorDate: Sun Oct 2 13:41:49 2022 +0200

    WW-5233 Copies Tiles Template related tests
---
 .../tiles/template/AddAttributeModelTest.java      | 111 ++++++++
 .../tiles/template/AddListAttributeModelTest.java  |  86 ++++++
 .../tiles/template/ComposeStackUtilTest.java       | 123 ++++++++
 .../template/DefaultAttributeResolverTest.java     | 155 ++++++++++
 .../apache/tiles/template/DefinitionModelTest.java |  98 +++++++
 .../tiles/template/GetAsStringModelTest.java       | 140 +++++++++
 .../tiles/template/ImportAttributeModelTest.java   | 316 +++++++++++++++++++++
 .../tiles/template/InsertAttributeModelTest.java   | 131 +++++++++
 .../tiles/template/InsertDefinitionModelTest.java  |  90 ++++++
 .../tiles/template/InsertTemplateModelTest.java    |  89 ++++++
 .../tiles/template/PutAttributeModelTest.java      |  93 ++++++
 .../tiles/template/PutListAttributeModelTest.java  |  93 ++++++
 .../template/SetCurrentContainerModelTest.java     |  84 ++++++
 13 files changed, 1609 insertions(+)

diff --git a/plugins/tiles/src/test/java/org/apache/tiles/template/AddAttributeModelTest.java b/plugins/tiles/src/test/java/org/apache/tiles/template/AddAttributeModelTest.java
new file mode 100644
index 000000000..86da99995
--- /dev/null
+++ b/plugins/tiles/src/test/java/org/apache/tiles/template/AddAttributeModelTest.java
@@ -0,0 +1,111 @@
+/*
+ * 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.template;
+
+import org.apache.tiles.api.Attribute;
+import org.apache.tiles.api.ListAttribute;
+import org.apache.tiles.autotag.core.runtime.ModelBody;
+import org.apache.tiles.request.Request;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.List;
+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;
+
+/**
+ * Tests {@link AddAttributeModel}.
+ */
+public class AddAttributeModelTest {
+
+    /**
+     * The model to test.
+     */
+    private AddAttributeModel model;
+
+    /**
+     * Sets up the test.
+     */
+    @Before
+    public void setUp() {
+        model = new AddAttributeModel();
+    }
+
+    /**
+     * Test method for {@link AddAttributeModel
+     * #execute(java.lang.Object, java.lang.String, java.lang.String, java.lang.String,
+     * Request, ModelBody)}.
+     *
+     * @throws IOException If something goes wrong.
+     */
+    @Test
+    public void testExecute() throws IOException {
+        Request request = createMock(Request.class);
+        ModelBody modelBody = createMock(ModelBody.class);
+        Deque<Object> composeStack = new ArrayDeque<>();
+        ListAttribute listAttribute = new ListAttribute();
+        Attribute attribute;
+        composeStack.push(listAttribute);
+        Map<String, Object> requestScope = new HashMap<>();
+        requestScope.put(ComposeStackUtil.COMPOSE_STACK_ATTRIBUTE_NAME, composeStack);
+
+        expect(request.getContext("request")).andReturn(requestScope).times(2);
+        expect(modelBody.evaluateAsString()).andReturn(null);
+        expect(modelBody.evaluateAsString()).andReturn("myBody");
+
+        replay(request, modelBody);
+        model.execute("myValue", "myExpression", "myRole", "myType",
+            request, modelBody);
+        List<Attribute> attributes = listAttribute.getValue();
+        assertEquals(1, attributes.size());
+        attribute = attributes.iterator().next();
+        assertEquals("myValue", attribute.getValue());
+        assertEquals("myExpression", attribute.getExpressionObject().getExpression());
+        assertEquals("myRole", attribute.getRole());
+        assertEquals("myType", attribute.getRenderer());
+
+        composeStack.clear();
+        listAttribute = new ListAttribute();
+        attribute = new Attribute();
+        composeStack.push(listAttribute);
+        composeStack.push(attribute);
+
+        model.execute(null, "myExpression", "myRole", "myType", request,
+            modelBody);
+        attributes = listAttribute.getValue();
+        assertEquals(1, attributes.size());
+        attribute = attributes.iterator().next();
+        assertEquals("myBody", attribute.getValue());
+        assertEquals("myExpression", attribute.getExpressionObject()
+            .getExpression());
+        assertEquals("myRole", attribute.getRole());
+        assertEquals("myType", attribute.getRenderer());
+        verify(request, modelBody);
+    }
+
+}
diff --git a/plugins/tiles/src/test/java/org/apache/tiles/template/AddListAttributeModelTest.java b/plugins/tiles/src/test/java/org/apache/tiles/template/AddListAttributeModelTest.java
new file mode 100644
index 000000000..3bdf11f5f
--- /dev/null
+++ b/plugins/tiles/src/test/java/org/apache/tiles/template/AddListAttributeModelTest.java
@@ -0,0 +1,86 @@
+/*
+ * 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.template;
+
+import org.apache.tiles.api.ListAttribute;
+import org.apache.tiles.autotag.core.runtime.ModelBody;
+import org.apache.tiles.request.Request;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.HashMap;
+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;
+
+/**
+ * Tests {@link AddListAttributeModel}.
+ */
+public class AddListAttributeModelTest {
+
+    /**
+     * The model to test.
+     */
+    private AddListAttributeModel model;
+
+    /**
+     * Sets up the test.
+     */
+    @Before
+    public void setUp() {
+        model = new AddListAttributeModel();
+    }
+
+    /**
+     * Test method for
+     * {@link AddListAttributeModel#execute(String, Request, ModelBody)}
+     * .
+     *
+     * @throws IOException If something goes wrong.
+     */
+    @Test
+    public void testExecute() throws IOException {
+        Deque<Object> composeStack = new ArrayDeque<>();
+        Request request = createMock(Request.class);
+        Map<String, Object> requestScope = new HashMap<>();
+        ModelBody modelBody = createMock(ModelBody.class);
+
+        modelBody.evaluateWithoutWriting();
+        requestScope.put(ComposeStackUtil.COMPOSE_STACK_ATTRIBUTE_NAME, composeStack);
+        expect(request.getContext("request")).andReturn(requestScope);
+
+        replay(request, modelBody);
+        ListAttribute parent = new ListAttribute();
+        composeStack.push(parent);
+        model.execute("myRole", request, modelBody);
+        assertEquals(1, composeStack.size());
+        assertEquals(parent, composeStack.pop());
+        assertEquals(1, parent.getValue().size());
+        ListAttribute listAttribute = (ListAttribute) parent.getValue().get(0);
+        assertEquals("myRole", listAttribute.getRole());
+        verify(request, modelBody);
+    }
+}
diff --git a/plugins/tiles/src/test/java/org/apache/tiles/template/ComposeStackUtilTest.java b/plugins/tiles/src/test/java/org/apache/tiles/template/ComposeStackUtilTest.java
new file mode 100644
index 000000000..cdfbab26e
--- /dev/null
+++ b/plugins/tiles/src/test/java/org/apache/tiles/template/ComposeStackUtilTest.java
@@ -0,0 +1,123 @@
+/*
+ * 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.template;
+
+import org.apache.tiles.request.Request;
+import org.junit.Test;
+
+import java.util.ArrayDeque;
+import java.util.Date;
+import java.util.Deque;
+import java.util.HashMap;
+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.assertNull;
+import static org.junit.Assert.assertSame;
+
+/**
+ * Tests {@link ComposeStackUtil}.
+ */
+public class ComposeStackUtilTest {
+
+    /**
+     * An integer value.
+     */
+    private static final int INT_VALUE = 3;
+
+    /**
+     * A long value.
+     */
+    private static final long LONG_VALUE = 2L;
+
+    /**
+     * Test method for {@link ComposeStackUtil
+     * #findAncestorWithClass(java.util.Stack, java.lang.Class)}.
+     */
+    @Test
+    public void testFindAncestorWithClass() {
+        Deque<Object> composeStack = new ArrayDeque<>();
+        Integer integerValue = 1;
+        Long longValue = LONG_VALUE;
+        String stringValue = "my value";
+        Integer integerValue2 = INT_VALUE;
+        composeStack.push(integerValue);
+        composeStack.push(longValue);
+        composeStack.push(stringValue);
+        composeStack.push(integerValue2);
+        assertEquals(integerValue2, ComposeStackUtil.findAncestorWithClass(composeStack, Integer.class));
+        assertEquals(longValue, ComposeStackUtil.findAncestorWithClass(composeStack, Long.class));
+        assertEquals(stringValue, ComposeStackUtil.findAncestorWithClass(composeStack, String.class));
+        assertEquals(integerValue2, ComposeStackUtil.findAncestorWithClass(composeStack, Object.class));
+        assertNull(ComposeStackUtil.findAncestorWithClass(composeStack, Date.class));
+    }
+
+    /**
+     * Tests {@link ComposeStackUtil#getComposeStack(Request)}.
+     */
+    @Test
+    public void testGetComposeStackNull() {
+        Request request = createMock(Request.class);
+
+        Map<String, Object> requestScope = new HashMap<>();
+        expect(request.getContext("request")).andReturn(requestScope);
+
+        replay(request);
+        assertSame(ComposeStackUtil.getComposeStack(request),
+            requestScope.get(ComposeStackUtil.COMPOSE_STACK_ATTRIBUTE_NAME));
+        verify(request);
+    }
+
+    /**
+     * Tests {@link ComposeStackUtil#getComposeStack(Request)}.
+     */
+    @Test
+    public void testGetComposeStackNotNull() {
+        Request request = createMock(Request.class);
+        Deque<Object> composeStack = createMock(Deque.class);
+
+        Map<String, Object> requestScope = new HashMap<>();
+        requestScope.put(ComposeStackUtil.COMPOSE_STACK_ATTRIBUTE_NAME, composeStack);
+        expect(request.getContext("request")).andReturn(requestScope);
+
+        replay(request, composeStack);
+        assertSame(composeStack, ComposeStackUtil.getComposeStack(request));
+        verify(request, composeStack);
+    }
+
+    /**
+     * Tests {@link ComposeStackUtil#getComposeStack(Request)}.
+     */
+    @Test
+    public void testGetComposeStackNoNull() {
+        Request request = createMock(Request.class);
+
+        Map<String, Object> requestScope = new HashMap<>();
+        expect(request.getContext("request")).andReturn(requestScope);
+
+        replay(request);
+        assertSame(ComposeStackUtil.getComposeStack(request),
+            requestScope.get(ComposeStackUtil.COMPOSE_STACK_ATTRIBUTE_NAME));
+        verify(request);
+    }
+}
diff --git a/plugins/tiles/src/test/java/org/apache/tiles/template/DefaultAttributeResolverTest.java b/plugins/tiles/src/test/java/org/apache/tiles/template/DefaultAttributeResolverTest.java
new file mode 100644
index 000000000..ad51c1f70
--- /dev/null
+++ b/plugins/tiles/src/test/java/org/apache/tiles/template/DefaultAttributeResolverTest.java
@@ -0,0 +1,155 @@
+/*
+ * 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.template;
+
+import org.apache.tiles.api.Attribute;
+import org.apache.tiles.api.AttributeContext;
+import org.apache.tiles.api.Expression;
+import org.apache.tiles.api.TilesContainer;
+import org.apache.tiles.request.Request;
+import org.junit.Before;
+import org.junit.Test;
+
+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.assertNull;
+
+/**
+ * Tests {@link DefaultAttributeResolver}.
+ */
+public class DefaultAttributeResolverTest {
+
+    /**
+     * The resolver to test.
+     */
+    private DefaultAttributeResolver resolver;
+
+    /**
+     * Sets up the test.
+     */
+    @Before
+    public void setUp() {
+        resolver = new DefaultAttributeResolver();
+    }
+
+    /**
+     * Test method for {@link DefaultAttributeResolver
+     * #computeAttribute(org.apache.tiles.TilesContainer, org.apache.tiles.Attribute,
+     * java.lang.String, java.lang.String, boolean, java.lang.Object, java.lang.String,
+     * java.lang.String, Request)}.
+     */
+    @Test
+    public void testComputeAttributeInContext() {
+        TilesContainer container = createMock(TilesContainer.class);
+        AttributeContext attributeContext = createMock(AttributeContext.class);
+        Request request = createMock(Request.class);
+        Attribute attribute = new Attribute("myValue", Expression.createExpression("myExpression", null), "myRole", "myRenderer");
+
+        expect(container.getAttributeContext(request)).andReturn(attributeContext);
+        expect(attributeContext.getAttribute("myName")).andReturn(attribute);
+
+        replay(container, attributeContext, request);
+        assertEquals(attribute, resolver.computeAttribute(container, null, "myName", null, false, null, null, null, request));
+        verify(container, attributeContext, request);
+    }
+
+    /**
+     * Test method for {@link DefaultAttributeResolver
+     * #computeAttribute(org.apache.tiles.TilesContainer, org.apache.tiles.Attribute,
+     * java.lang.String, java.lang.String, boolean, java.lang.Object, java.lang.String,
+     * java.lang.String, Request)}.
+     */
+    @Test
+    public void testComputeAttributeInCall() {
+        TilesContainer container = createMock(TilesContainer.class);
+        Request request = createMock(Request.class);
+        Attribute attribute = new Attribute("myValue", Expression.createExpression("myExpression", null), "myRole", "myRenderer");
+
+        replay(container, request);
+        assertEquals(attribute, resolver.computeAttribute(container, attribute, null, null, false, null, null, null, request));
+        verify(container, request);
+    }
+
+    /**
+     * Test method for {@link DefaultAttributeResolver
+     * #computeAttribute(org.apache.tiles.TilesContainer, org.apache.tiles.Attribute,
+     * java.lang.String, java.lang.String, boolean, java.lang.Object, java.lang.String,
+     * java.lang.String, Request)}.
+     */
+    @Test
+    public void testComputeAttributeDefault() {
+        TilesContainer container = createMock(TilesContainer.class);
+        Request request = createMock(Request.class);
+        AttributeContext attributeContext = createMock(AttributeContext.class);
+
+        expect(container.getAttributeContext(request)).andReturn(attributeContext);
+        expect(attributeContext.getAttribute("myName")).andReturn(null);
+
+        replay(container, attributeContext, request);
+        Attribute attribute = resolver.computeAttribute(container, null, "myName", null, false, "defaultValue", "defaultRole", "defaultType", request);
+        assertEquals("defaultValue", attribute.getValue());
+        assertEquals("defaultRole", attribute.getRole());
+        assertEquals("defaultType", attribute.getRenderer());
+        verify(container, attributeContext, request);
+    }
+
+    /**
+     * Test method for {@link DefaultAttributeResolver
+     * #computeAttribute(org.apache.tiles.TilesContainer, org.apache.tiles.Attribute,
+     * java.lang.String, java.lang.String, boolean, java.lang.Object, java.lang.String,
+     * java.lang.String, Request)}.
+     */
+    @Test(expected = NoSuchAttributeException.class)
+    public void testComputeAttributeException() {
+        TilesContainer container = createMock(TilesContainer.class);
+        AttributeContext attributeContext = createMock(AttributeContext.class);
+        Request request = createMock(Request.class);
+
+        expect(container.getAttributeContext(request)).andReturn(attributeContext);
+        expect(attributeContext.getAttribute("myName")).andReturn(null);
+
+        replay(container, attributeContext, request);
+        resolver.computeAttribute(container, null, "myName", null, false, null, "defaultRole", "defaultType", request);
+        verify(container, attributeContext, request);
+    }
+
+    /**
+     * Test method for {@link DefaultAttributeResolver
+     * #computeAttribute(org.apache.tiles.TilesContainer, org.apache.tiles.Attribute,
+     * java.lang.String, java.lang.String, boolean, java.lang.Object, java.lang.String,
+     * java.lang.String, Request)}.
+     */
+    @Test
+    public void testComputeAttributeIgnore() {
+        TilesContainer container = createMock(TilesContainer.class);
+        AttributeContext attributeContext = createMock(AttributeContext.class);
+        Request request = createMock(Request.class);
+
+        expect(container.getAttributeContext(request)).andReturn(attributeContext);
+        expect(attributeContext.getAttribute("myName")).andReturn(null);
+
+        replay(container, attributeContext, request);
+        assertNull(resolver.computeAttribute(container, null, "myName", null, true, null, "defaultRole", "defaultType", request));
+        verify(container, attributeContext, request);
+    }
+}
diff --git a/plugins/tiles/src/test/java/org/apache/tiles/template/DefinitionModelTest.java b/plugins/tiles/src/test/java/org/apache/tiles/template/DefinitionModelTest.java
new file mode 100644
index 000000000..44511452f
--- /dev/null
+++ b/plugins/tiles/src/test/java/org/apache/tiles/template/DefinitionModelTest.java
@@ -0,0 +1,98 @@
+/*
+ * 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.template;
+
+import org.apache.tiles.api.Attribute;
+import org.apache.tiles.api.access.TilesAccess;
+import org.apache.tiles.api.mgmt.MutableTilesContainer;
+import org.apache.tiles.autotag.core.runtime.ModelBody;
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.Request;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.eq;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.notNull;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * Tests {@link DefinitionModel}.
+ */
+public class DefinitionModelTest {
+
+    /**
+     * The model to test.
+     */
+    private DefinitionModel model;
+
+    /**
+     * Sets up the test.
+     */
+    @Before
+    public void setUp() {
+        model = new DefinitionModel();
+    }
+
+    /**
+     * Test method for {@link DefinitionModel
+     * #execute(java.lang.String, java.lang.String,
+     * java.lang.String, java.lang.String, java.lang.String, Request, ModelBody)}.
+     *
+     * @throws IOException If something goes wrong.
+     */
+    @Test
+    public void testExecute() throws IOException {
+        MutableTilesContainer container = createMock(MutableTilesContainer.class);
+        Request request = createMock(Request.class);
+        Deque<Object> composeStack = new ArrayDeque<>();
+        Attribute attribute = new Attribute();
+        composeStack.push(attribute);
+        Map<String, Object> requestScope = new HashMap<>();
+        requestScope.put(ComposeStackUtil.COMPOSE_STACK_ATTRIBUTE_NAME, composeStack);
+        requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container);
+        ApplicationContext applicationContext = createMock(ApplicationContext.class);
+        ModelBody modelBody = createMock(ModelBody.class);
+
+        modelBody.evaluateWithoutWriting();
+        expect(request.getApplicationContext()).andReturn(applicationContext);
+        expect(request.getContext("request")).andReturn(requestScope).anyTimes();
+        container.register(notNull(), eq(request));
+
+        replay(container, request, modelBody, applicationContext);
+        model.execute("myName", "myTemplate", "myRole", "myExtends",
+            "myPreparer", request, modelBody);
+        assertEquals(1, composeStack.size());
+        attribute = (Attribute) composeStack.peek();
+        assertNotNull(attribute);
+        assertEquals("definition", attribute.getRenderer());
+        verify(container, request, modelBody, applicationContext);
+    }
+
+}
diff --git a/plugins/tiles/src/test/java/org/apache/tiles/template/GetAsStringModelTest.java b/plugins/tiles/src/test/java/org/apache/tiles/template/GetAsStringModelTest.java
new file mode 100644
index 000000000..8a8bbeee1
--- /dev/null
+++ b/plugins/tiles/src/test/java/org/apache/tiles/template/GetAsStringModelTest.java
@@ -0,0 +1,140 @@
+/*
+ * 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.template;
+
+import org.apache.tiles.api.Attribute;
+import org.apache.tiles.api.AttributeContext;
+import org.apache.tiles.api.TilesContainer;
+import org.apache.tiles.api.access.TilesAccess;
+import org.apache.tiles.autotag.core.runtime.ModelBody;
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.Request;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.HashMap;
+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;
+
+/**
+ * Tests {@link GetAsStringModel}.
+ */
+public class GetAsStringModelTest {
+
+    /**
+     * The mock resolver.
+     */
+    private AttributeResolver resolver;
+
+    /**
+     * The model to test.
+     */
+    private GetAsStringModel model;
+
+    /**
+     * Sets up the test.
+     */
+    @Before
+    public void setUp() {
+        resolver = createMock(AttributeResolver.class);
+        model = new GetAsStringModel(resolver);
+    }
+
+    /**
+     * Test method for {@link GetAsStringModel
+     * #execute(boolean, java.lang.String, java.lang.String,
+     * java.lang.Object, java.lang.String, java.lang.String, java.lang.String,
+     * org.apache.tiles.Attribute, Request, ModelBody)}.
+     *
+     * @throws IOException If something goes wrong.
+     */
+    @Test
+    public void testExecute() throws IOException {
+        TilesContainer container = createMock(TilesContainer.class);
+        Attribute attribute = createMock(Attribute.class);
+        AttributeContext attributeContext = createMock(AttributeContext.class);
+        Request request = createMock(Request.class);
+        Writer writer = createMock(Writer.class);
+        Map<String, Object> requestScope = new HashMap<>();
+        Deque<Object> composeStack = new ArrayDeque<>();
+        requestScope.put(ComposeStackUtil.COMPOSE_STACK_ATTRIBUTE_NAME, composeStack);
+        requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container);
+        ApplicationContext applicationContext = createMock(ApplicationContext.class);
+        ModelBody modelBody = createMock(ModelBody.class);
+
+        modelBody.evaluateWithoutWriting();
+        expect(request.getApplicationContext()).andReturn(applicationContext).times(2);
+        expect(request.getContext("request")).andReturn(requestScope).anyTimes();
+        expect(request.getWriter()).andReturn(writer);
+        container.prepare("myPreparer", request);
+        expect(resolver.computeAttribute(container, attribute, "myName", "myRole", false, "myDefaultValue", "myDefaultValueRole", "myDefaultValueType", request)).andReturn(attribute);
+        expect(container.startContext(request)).andReturn(attributeContext);
+        expect(container.evaluate(attribute, request)).andReturn("myValue");
+        writer.write("myValue");
+        container.endContext(request);
+
+        replay(resolver, container, writer, request, applicationContext, modelBody);
+        model.execute(false, "myPreparer", "myRole", "myDefaultValue", "myDefaultValueRole", "myDefaultValueType", "myName", attribute, request, modelBody);
+        verify(resolver, container, writer, request, applicationContext, modelBody);
+    }
+
+    /**
+     * Test method for {@link GetAsStringModel
+     * #execute(boolean, java.lang.String, java.lang.String,
+     * java.lang.Object, java.lang.String, java.lang.String, java.lang.String,
+     * org.apache.tiles.Attribute, Request, ModelBody)} when ignore flag is set.
+     *
+     * @throws IOException If something goes wrong.
+     */
+    @Test
+    public void testExecuteIgnore() throws IOException {
+        TilesContainer container = createMock(TilesContainer.class);
+        AttributeContext attributeContext = createMock(AttributeContext.class);
+        Request request = createMock(Request.class);
+        Writer writer = createMock(Writer.class);
+        Map<String, Object> requestScope = new HashMap<>();
+        Deque<Object> composeStack = new ArrayDeque<>();
+        requestScope.put(ComposeStackUtil.COMPOSE_STACK_ATTRIBUTE_NAME, composeStack);
+        requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container);
+        ApplicationContext applicationContext = createMock(ApplicationContext.class);
+        ModelBody modelBody = createMock(ModelBody.class);
+
+        modelBody.evaluateWithoutWriting();
+        expect(request.getApplicationContext()).andReturn(applicationContext).times(2);
+        expect(request.getContext("request")).andReturn(requestScope).anyTimes();
+        expect(request.getWriter()).andReturn(writer);
+        container.prepare("myPreparer", request);
+        expect(resolver.computeAttribute(container, null, "myName", "myRole", true, "myDefaultValue", "myDefaultValueRole", "myDefaultValueType", request)).andReturn(null);
+        expect(container.startContext(request)).andReturn(attributeContext);
+        container.endContext(request);
+
+        replay(resolver, container, writer, request, applicationContext, modelBody);
+        model.execute(true, "myPreparer", "myRole", "myDefaultValue", "myDefaultValueRole", "myDefaultValueType", "myName", null, request, modelBody);
+        verify(resolver, container, writer, request, applicationContext, modelBody);
+    }
+
+}
diff --git a/plugins/tiles/src/test/java/org/apache/tiles/template/ImportAttributeModelTest.java b/plugins/tiles/src/test/java/org/apache/tiles/template/ImportAttributeModelTest.java
new file mode 100644
index 000000000..73a10121e
--- /dev/null
+++ b/plugins/tiles/src/test/java/org/apache/tiles/template/ImportAttributeModelTest.java
@@ -0,0 +1,316 @@
+/*
+ * 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.template;
+
+import org.apache.tiles.api.Attribute;
+import org.apache.tiles.api.AttributeContext;
+import org.apache.tiles.api.TilesContainer;
+import org.apache.tiles.api.access.TilesAccess;
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.Request;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+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;
+
+/**
+ * Tests {@link ImportAttributeModel}.
+ */
+public class ImportAttributeModelTest {
+
+    /**
+     * The size of the attributes collection.
+     */
+    private static final int ATTRIBUTES_SIZE = 4;
+
+    /**
+     * The model to test.
+     */
+    private ImportAttributeModel model;
+
+    /**
+     * Sets up the test.
+     */
+    @Before
+    public void setUp() {
+        model = new ImportAttributeModel();
+    }
+
+    /**
+     * Test method for {@link ImportAttributeModel
+     * #execute(String, String, String, boolean, Request).
+     */
+    @Test
+    public void testExecuteSingle() {
+        TilesContainer container = createMock(TilesContainer.class);
+        AttributeContext attributeContext = createMock(AttributeContext.class);
+        Attribute attribute = new Attribute();
+        Request request = createMock(Request.class);
+        ApplicationContext applicationContext = createMock(ApplicationContext.class);
+        Map<String, Object> requestScope = new HashMap<>();
+        requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container);
+
+        expect(request.getApplicationContext()).andReturn(applicationContext);
+        expect(request.getContext("request")).andReturn(requestScope).anyTimes();
+        expect(container.getAttributeContext(request)).andReturn(attributeContext);
+        expect(attributeContext.getAttribute("myName")).andReturn(attribute);
+        expect(container.evaluate(attribute, request)).andReturn("myEvaluatedValue");
+
+        replay(container, attributeContext, request, applicationContext);
+        model.execute("myName", "request", null, false, request);
+        assertEquals(2, requestScope.size());
+        assertEquals("myEvaluatedValue", requestScope.get("myName"));
+        verify(container, attributeContext, request, applicationContext);
+    }
+
+    /**
+     * Test method for {@link ImportAttributeModel
+     * #execute(String, String, String, boolean, Request).
+     */
+    @Test
+    public void testExecuteSingleToName() {
+        TilesContainer container = createMock(TilesContainer.class);
+        Request request = createMock(Request.class);
+        AttributeContext attributeContext = createMock(AttributeContext.class);
+        Attribute attribute = new Attribute();
+        ApplicationContext applicationContext = createMock(ApplicationContext.class);
+        Map<String, Object> requestScope = new HashMap<>();
+        requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container);
+
+        expect(request.getApplicationContext()).andReturn(applicationContext);
+        expect(request.getContext("request")).andReturn(requestScope).anyTimes();
+        expect(container.getAttributeContext(request)).andReturn(attributeContext);
+        expect(attributeContext.getAttribute("myName")).andReturn(attribute);
+        expect(container.evaluate(attribute, request)).andReturn("myEvaluatedValue");
+
+        replay(container, attributeContext, request, applicationContext);
+        model.execute("myName", "request", "myToName", false, request);
+        assertEquals(2, requestScope.size());
+        assertEquals("myEvaluatedValue", requestScope.get("myToName"));
+        verify(container, attributeContext, request, applicationContext);
+    }
+
+    /**
+     * Test method for {@link ImportAttributeModel
+     * #execute(String, String, String, boolean, Request).
+     */
+    @Test
+    public void testExecuteAll() {
+        TilesContainer container = createMock(TilesContainer.class);
+        Request request = createMock(Request.class);
+        AttributeContext attributeContext = createMock(AttributeContext.class);
+        Attribute attribute1 = new Attribute("myValue1");
+        Attribute attribute2 = new Attribute("myValue2");
+        Attribute attribute3 = new Attribute("myValue3");
+        Set<String> cascadedNames = new HashSet<>();
+        cascadedNames.add("myName1");
+        cascadedNames.add("myName2");
+        Set<String> localNames = new HashSet<>();
+        localNames.add("myName1");
+        localNames.add("myName3");
+        ApplicationContext applicationContext = createMock(ApplicationContext.class);
+        Map<String, Object> requestScope = new HashMap<>();
+        requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container);
+
+        expect(request.getApplicationContext()).andReturn(applicationContext);
+        expect(request.getContext("request")).andReturn(requestScope).anyTimes();
+        expect(container.getAttributeContext(request)).andReturn(attributeContext);
+        expect(attributeContext.getCascadedAttributeNames()).andReturn(cascadedNames);
+        expect(attributeContext.getLocalAttributeNames()).andReturn(localNames);
+        expect(attributeContext.getAttribute("myName1")).andReturn(attribute1).times(2);
+        expect(attributeContext.getAttribute("myName2")).andReturn(attribute2);
+        expect(attributeContext.getAttribute("myName3")).andReturn(attribute3);
+        expect(container.evaluate(attribute1, request)).andReturn("myEvaluatedValue1").times(2);
+        expect(container.evaluate(attribute2, request)).andReturn("myEvaluatedValue2");
+        expect(container.evaluate(attribute3, request)).andReturn("myEvaluatedValue3");
+
+        replay(container, attributeContext, request, applicationContext);
+        model.execute(null, "request", null, false, request);
+        assertEquals(ATTRIBUTES_SIZE, requestScope.size());
+        assertEquals("myEvaluatedValue1", requestScope.get("myName1"));
+        assertEquals("myEvaluatedValue2", requestScope.get("myName2"));
+        assertEquals("myEvaluatedValue3", requestScope.get("myName3"));
+        verify(container, attributeContext, request, applicationContext);
+    }
+
+    /**
+     * Test method for {@link ImportAttributeModel
+     * #execute(String, String, String, boolean, Request).
+     */
+    @Test(expected = NoSuchAttributeException.class)
+    public void testExecuteSingleNullAttributeException() {
+        TilesContainer container = createMock(TilesContainer.class);
+        Request request = createMock(Request.class);
+        AttributeContext attributeContext = createMock(AttributeContext.class);
+        ApplicationContext applicationContext = createMock(ApplicationContext.class);
+        Map<String, Object> requestScope = new HashMap<>();
+        requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container);
+
+        expect(request.getApplicationContext()).andReturn(applicationContext);
+        expect(request.getContext("request")).andReturn(requestScope).anyTimes();
+        expect(container.getAttributeContext(request)).andReturn(attributeContext);
+        expect(attributeContext.getAttribute("myName")).andReturn(null);
+
+        replay(container, attributeContext, request, applicationContext);
+        try {
+            model.execute("myName", "request", null, false, request);
+        } finally {
+            verify(container, attributeContext, request, applicationContext);
+        }
+    }
+
+    /**
+     * Test method for {@link ImportAttributeModel
+     * #execute(String, String, String, boolean, Request).
+     */
+    @Test(expected = NoSuchAttributeException.class)
+    public void testExecuteSingleNullAttributeValueException() {
+        TilesContainer container = createMock(TilesContainer.class);
+        Request request = createMock(Request.class);
+        AttributeContext attributeContext = createMock(AttributeContext.class);
+        Attribute attribute = new Attribute();
+        ApplicationContext applicationContext = createMock(ApplicationContext.class);
+        Map<String, Object> requestScope = new HashMap<>();
+        requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container);
+
+        expect(request.getApplicationContext()).andReturn(applicationContext);
+        expect(request.getContext("request")).andReturn(requestScope).anyTimes();
+        expect(container.getAttributeContext(request)).andReturn(attributeContext);
+        expect(attributeContext.getAttribute("myName")).andReturn(attribute);
+        expect(container.evaluate(attribute, request)).andReturn(null);
+
+        replay(container, attributeContext, request, applicationContext);
+        try {
+            model.execute("myName", "request", null, false, request);
+        } finally {
+            verify(container, attributeContext, request, applicationContext);
+        }
+    }
+
+    /**
+     * Test method for {@link ImportAttributeModel
+     * #execute(String, String, String, boolean, Request).
+     */
+    @Test(expected = RuntimeException.class)
+    public void testExecuteSingleRuntimeException() {
+        TilesContainer container = createMock(TilesContainer.class);
+        Request request = createMock(Request.class);
+        AttributeContext attributeContext = createMock(AttributeContext.class);
+        Attribute attribute = new Attribute();
+        ApplicationContext applicationContext = createMock(ApplicationContext.class);
+        Map<String, Object> requestScope = new HashMap<>();
+        requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container);
+
+        expect(request.getApplicationContext()).andReturn(applicationContext);
+        expect(request.getContext("request")).andReturn(requestScope).anyTimes();
+        expect(container.getAttributeContext(request)).andReturn(attributeContext);
+        expect(attributeContext.getAttribute("myName")).andReturn(attribute);
+        expect(container.evaluate(attribute, request)).andThrow(new RuntimeException());
+
+        replay(container, attributeContext, request, applicationContext);
+        try {
+            model.execute("myName", "request", null, false, request);
+        } finally {
+            verify(container, attributeContext, request, applicationContext);
+        }
+    }
+
+    /**
+     * Test method for {@link ImportAttributeModel
+     * #execute(String, String, String, boolean, Request).
+     */
+    @Test
+    public void testExecuteSingleNullAttributeIgnore() {
+        TilesContainer container = createMock(TilesContainer.class);
+        Request request = createMock(Request.class);
+        AttributeContext attributeContext = createMock(AttributeContext.class);
+        ApplicationContext applicationContext = createMock(ApplicationContext.class);
+        Map<String, Object> requestScope = new HashMap<>();
+        requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container);
+
+        expect(request.getApplicationContext()).andReturn(applicationContext);
+        expect(request.getContext("request")).andReturn(requestScope).anyTimes();
+        expect(container.getAttributeContext(request)).andReturn(attributeContext);
+        expect(attributeContext.getAttribute("myName")).andReturn(null);
+
+        replay(container, attributeContext, request, applicationContext);
+        model.execute("myName", "request", null, true, request);
+        verify(container, attributeContext, request, applicationContext);
+    }
+
+    /**
+     * Test method for {@link ImportAttributeModel
+     * #execute(String, String, String, boolean, Request).
+     */
+    @Test
+    public void testExecuteSingleNullAttributeValueIgnore() {
+        TilesContainer container = createMock(TilesContainer.class);
+        Request request = createMock(Request.class);
+        AttributeContext attributeContext = createMock(AttributeContext.class);
+        Attribute attribute = new Attribute();
+        ApplicationContext applicationContext = createMock(ApplicationContext.class);
+        Map<String, Object> requestScope = new HashMap<>();
+        requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container);
+
+        expect(request.getApplicationContext()).andReturn(applicationContext);
+        expect(request.getContext("request")).andReturn(requestScope).anyTimes();
+        expect(container.getAttributeContext(request)).andReturn(attributeContext);
+        expect(attributeContext.getAttribute("myName")).andReturn(attribute);
+        expect(container.evaluate(attribute, request)).andReturn(null);
+
+        replay(container, attributeContext, request, applicationContext);
+        model.execute("myName", "request", null, true, request);
+        verify(container, attributeContext, request, applicationContext);
+    }
+
+    /**
+     * Test method for {@link ImportAttributeModel
+     * #execute(String, String, String, boolean, Request).
+     */
+    @Test
+    public void testExecuteSingleRuntimeIgnore() {
+        TilesContainer container = createMock(TilesContainer.class);
+        Request request = createMock(Request.class);
+        AttributeContext attributeContext = createMock(AttributeContext.class);
+        Attribute attribute = new Attribute();
+        ApplicationContext applicationContext = createMock(ApplicationContext.class);
+        Map<String, Object> requestScope = new HashMap<>();
+        requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container);
+
+        expect(request.getApplicationContext()).andReturn(applicationContext);
+        expect(request.getContext("request")).andReturn(requestScope).anyTimes();
+        expect(container.getAttributeContext(request)).andReturn(attributeContext);
+        expect(attributeContext.getAttribute("myName")).andReturn(attribute);
+        expect(container.evaluate(attribute, request)).andThrow(new RuntimeException());
+
+        replay(container, attributeContext, request, applicationContext);
+        model.execute("myName", "request", null, true, request);
+        verify(container, attributeContext, request, applicationContext);
+    }
+}
diff --git a/plugins/tiles/src/test/java/org/apache/tiles/template/InsertAttributeModelTest.java b/plugins/tiles/src/test/java/org/apache/tiles/template/InsertAttributeModelTest.java
new file mode 100644
index 000000000..e8a997ac0
--- /dev/null
+++ b/plugins/tiles/src/test/java/org/apache/tiles/template/InsertAttributeModelTest.java
@@ -0,0 +1,131 @@
+/*
+ * 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.template;
+
+import org.apache.tiles.api.Attribute;
+import org.apache.tiles.api.AttributeContext;
+import org.apache.tiles.api.TilesContainer;
+import org.apache.tiles.api.access.TilesAccess;
+import org.apache.tiles.autotag.core.runtime.ModelBody;
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.Request;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.HashMap;
+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;
+
+/**
+ * Tests {@link InsertAttributeModel}.
+ */
+public class InsertAttributeModelTest {
+
+    /**
+     * The mock resolver.
+     */
+    private AttributeResolver resolver;
+
+    /**
+     * The model to test.
+     */
+    private InsertAttributeModel model;
+
+    /**
+     * Sets up the test.
+     */
+    @Before
+    public void setUp() {
+        resolver = createMock(AttributeResolver.class);
+        model = new InsertAttributeModel(resolver);
+    }
+
+    /**
+     * Test method for {@link InsertAttributeModel
+     * #execute(boolean, String, String, Object, String, String, String,
+     * Attribute, boolean, Request, ModelBody)}.
+     *
+     * @throws IOException If something goes wrong.
+     */
+    @Test
+    public void testExecute() throws IOException {
+        TilesContainer container = createMock(TilesContainer.class);
+        Request request = createMock(Request.class);
+        Attribute attribute = new Attribute("myValue");
+        AttributeContext attributeContext = createMock(AttributeContext.class);
+        Map<String, Object> requestScope = new HashMap<>();
+        requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container);
+        ApplicationContext applicationContext = createMock(ApplicationContext.class);
+        ModelBody modelBody = createMock(ModelBody.class);
+
+        modelBody.evaluateWithoutWriting();
+        expect(request.getApplicationContext()).andReturn(applicationContext).times(2);
+        expect(request.getContext("request")).andReturn(requestScope).anyTimes();
+
+        container.prepare("myPreparer", request);
+        expect(resolver.computeAttribute(container, attribute, "myName", "myRole", false, "myDefaultValue", "myDefaultValueRole", "myDefaultValueType", request)).andReturn(attribute);
+        expect(container.startContext(request)).andReturn(attributeContext);
+        container.endContext(request);
+        container.render(attribute, request);
+
+        replay(resolver, container, request, applicationContext, modelBody);
+        model.execute(false, "myPreparer", "myRole", "myDefaultValue", "myDefaultValueRole", "myDefaultValueType", "myName", attribute, false, request, modelBody);
+        verify(resolver, container, request, applicationContext, modelBody);
+    }
+
+    /**
+     * Test method for {@link InsertAttributeModel
+     * #execute(boolean, String, String, Object, String, String, String,
+     * Attribute, boolean, Request, ModelBody)} when ignore flag is set.
+     *
+     * @throws IOException If something goes wrong.
+     */
+    @Test
+    public void testExecuteIgnore() throws IOException {
+        TilesContainer container = createMock(TilesContainer.class);
+        Request request = createMock(Request.class);
+        AttributeContext attributeContext = createMock(AttributeContext.class);
+        Map<String, Object> requestScope = new HashMap<>();
+        Deque<Object> composeStack = new ArrayDeque<>();
+        requestScope.put(ComposeStackUtil.COMPOSE_STACK_ATTRIBUTE_NAME, composeStack);
+        requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container);
+        ApplicationContext applicationContext = createMock(ApplicationContext.class);
+        ModelBody modelBody = createMock(ModelBody.class);
+
+        modelBody.evaluateWithoutWriting();
+        expect(request.getApplicationContext()).andReturn(applicationContext).times(2);
+        expect(request.getContext("request")).andReturn(requestScope).anyTimes();
+
+        container.prepare("myPreparer", request);
+        expect(resolver.computeAttribute(container, null, "myName", "myRole", true, "myDefaultValue", "myDefaultValueRole", "myDefaultValueType", request)).andReturn(null);
+        expect(container.startContext(request)).andReturn(attributeContext);
+        container.endContext(request);
+
+        replay(resolver, container, request, applicationContext, modelBody);
+        model.execute(true, "myPreparer", "myRole", "myDefaultValue", "myDefaultValueRole", "myDefaultValueType", "myName", null, false, request, modelBody);
+        verify(resolver, container, request, applicationContext, modelBody);
+    }
+}
diff --git a/plugins/tiles/src/test/java/org/apache/tiles/template/InsertDefinitionModelTest.java b/plugins/tiles/src/test/java/org/apache/tiles/template/InsertDefinitionModelTest.java
new file mode 100644
index 000000000..48d3fb492
--- /dev/null
+++ b/plugins/tiles/src/test/java/org/apache/tiles/template/InsertDefinitionModelTest.java
@@ -0,0 +1,90 @@
+/*
+ * 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.template;
+
+import org.apache.tiles.api.AttributeContext;
+import org.apache.tiles.api.TilesContainer;
+import org.apache.tiles.api.access.TilesAccess;
+import org.apache.tiles.autotag.core.runtime.ModelBody;
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.Request;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.notNull;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
+/**
+ * Tests {@link InsertDefinitionModel}.
+ */
+public class InsertDefinitionModelTest {
+
+    /**
+     * The model to test.
+     */
+    private InsertDefinitionModel model;
+
+    /**
+     * Sets up the test.
+     */
+    @Before
+    public void setUp() {
+        model = new InsertDefinitionModel();
+    }
+
+    /**
+     * Test method for {@link InsertDefinitionModel
+     * #execute(java.lang.String, java.lang.String, String,
+     * String, java.lang.String, java.lang.String, boolean, Request, ModelBody)}.
+     *
+     * @throws IOException If something goes wrong.
+     */
+    @Test
+    public void testExecute() throws IOException {
+        TilesContainer container = createMock(TilesContainer.class);
+        Request request = createMock(Request.class);
+        AttributeContext attributeContext = createMock(AttributeContext.class);
+        Map<String, Object> requestScope = new HashMap<>();
+        requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container);
+        ApplicationContext applicationContext = createMock(ApplicationContext.class);
+        ModelBody modelBody = createMock(ModelBody.class);
+
+        modelBody.evaluateWithoutWriting();
+        expect(request.getApplicationContext()).andReturn(applicationContext).times(2);
+        expect(request.getContext("request")).andReturn(requestScope).anyTimes();
+        expect(container.startContext(request)).andReturn(attributeContext);
+        expect(container.getAttributeContext(request)).andReturn(attributeContext);
+        container.endContext(request);
+        attributeContext.setPreparer("myPreparer");
+        attributeContext.setTemplateAttribute(notNull());
+        container.render("myDefinitionName", request);
+
+        replay(container, attributeContext, request, applicationContext, modelBody);
+        model.execute("myDefinitionName", "myTemplate", "myTemplateType", "myTemplateExpression", "myRole", "myPreparer", false, request, modelBody);
+        verify(container, attributeContext, request, applicationContext, modelBody);
+    }
+
+}
diff --git a/plugins/tiles/src/test/java/org/apache/tiles/template/InsertTemplateModelTest.java b/plugins/tiles/src/test/java/org/apache/tiles/template/InsertTemplateModelTest.java
new file mode 100644
index 000000000..840593d7e
--- /dev/null
+++ b/plugins/tiles/src/test/java/org/apache/tiles/template/InsertTemplateModelTest.java
@@ -0,0 +1,89 @@
+/*
+ * 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.template;
+
+import org.apache.tiles.api.AttributeContext;
+import org.apache.tiles.api.TilesContainer;
+import org.apache.tiles.api.access.TilesAccess;
+import org.apache.tiles.autotag.core.runtime.ModelBody;
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.Request;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.notNull;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
+/**
+ * Tests {@link InsertTemplateModel}.
+ */
+public class InsertTemplateModelTest {
+
+    /**
+     * The model to test.
+     */
+    private InsertTemplateModel model;
+
+    /**
+     * Sets up the test.
+     */
+    @Before
+    public void setUp() {
+        model = new InsertTemplateModel();
+    }
+
+    /**
+     * Test method for {@link InsertTemplateModel
+     * #execute(String, String, String, String, String, boolean, Request, ModelBody)}.
+     *
+     * @throws IOException If something goes wrong.
+     */
+    @Test
+    public void testExecute() throws IOException {
+        TilesContainer container = createMock(TilesContainer.class);
+        Request request = createMock(Request.class);
+        AttributeContext attributeContext = createMock(AttributeContext.class);
+        Map<String, Object> requestScope = new HashMap<>();
+        requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container);
+        ApplicationContext applicationContext = createMock(ApplicationContext.class);
+        ModelBody modelBody = createMock(ModelBody.class);
+
+        modelBody.evaluateWithoutWriting();
+        expect(request.getApplicationContext()).andReturn(applicationContext).times(2);
+        expect(request.getContext("request")).andReturn(requestScope).anyTimes();
+        expect(container.startContext(request)).andReturn(attributeContext);
+        expect(container.getAttributeContext(request)).andReturn(attributeContext);
+        container.endContext(request);
+        attributeContext.setPreparer("myPreparer");
+        attributeContext.setTemplateAttribute(notNull());
+        container.renderContext(request);
+
+        replay(container, attributeContext, request, applicationContext, modelBody);
+        model.execute("myTemplate", "myTemplateType", "myTemplateExpression", "myRole", "myPreparer", false, request, modelBody);
+        verify(container, attributeContext, request, applicationContext, modelBody);
+    }
+
+}
diff --git a/plugins/tiles/src/test/java/org/apache/tiles/template/PutAttributeModelTest.java b/plugins/tiles/src/test/java/org/apache/tiles/template/PutAttributeModelTest.java
new file mode 100644
index 000000000..572dcad59
--- /dev/null
+++ b/plugins/tiles/src/test/java/org/apache/tiles/template/PutAttributeModelTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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.template;
+
+import org.apache.tiles.api.AttributeContext;
+import org.apache.tiles.api.ListAttribute;
+import org.apache.tiles.api.TilesContainer;
+import org.apache.tiles.api.access.TilesAccess;
+import org.apache.tiles.autotag.core.runtime.ModelBody;
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.Request;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.eq;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.notNull;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
+/**
+ * Tests {@link PutAttributeModel}.
+ */
+public class PutAttributeModelTest {
+
+    /**
+     * The model to test.
+     */
+    private PutAttributeModel model;
+
+    /**
+     * Sets up the test.
+     */
+    @Before
+    public void setUp() {
+        model = new PutAttributeModel();
+    }
+
+    /**
+     * Test method for {@link PutAttributeModel
+     * #execute(String, Object, String, String, String,
+     * boolean, Request, ModelBody)}.
+     *
+     * @throws IOException If something goes wrong.
+     */
+    @Test
+    public void testExecuteListAttribute() throws IOException {
+        TilesContainer container = createMock(TilesContainer.class);
+        Request request = createMock(Request.class);
+        ModelBody modelBody = createMock(ModelBody.class);
+        AttributeContext attributeContext = createMock(AttributeContext.class);
+        Deque<Object> composeStack = new ArrayDeque<>();
+        ListAttribute listAttribute = new ListAttribute();
+        composeStack.push(listAttribute);
+        Map<String, Object> requestScope = new HashMap<>();
+        requestScope.put(ComposeStackUtil.COMPOSE_STACK_ATTRIBUTE_NAME, composeStack);
+        requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container);
+        ApplicationContext applicationContext = createMock(ApplicationContext.class);
+
+        expect(request.getApplicationContext()).andReturn(applicationContext);
+        expect(request.getContext("request")).andReturn(requestScope).anyTimes();
+        expect(container.getAttributeContext(request)).andReturn(attributeContext);
+        attributeContext.putAttribute(eq("myName"), notNull(), eq(false));
+        expect(modelBody.evaluateAsString()).andReturn(null);
+
+        replay(container, attributeContext, request, applicationContext, modelBody);
+        model.execute("myName", "myValue", "myExpression", "myRole", "myType", false, request, modelBody);
+        verify(container, attributeContext, request, applicationContext, modelBody);
+    }
+}
diff --git a/plugins/tiles/src/test/java/org/apache/tiles/template/PutListAttributeModelTest.java b/plugins/tiles/src/test/java/org/apache/tiles/template/PutListAttributeModelTest.java
new file mode 100644
index 000000000..cd4708afc
--- /dev/null
+++ b/plugins/tiles/src/test/java/org/apache/tiles/template/PutListAttributeModelTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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.template;
+
+import org.apache.tiles.api.AttributeContext;
+import org.apache.tiles.api.ListAttribute;
+import org.apache.tiles.api.TilesContainer;
+import org.apache.tiles.api.access.TilesAccess;
+import org.apache.tiles.autotag.core.runtime.ModelBody;
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.Request;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.eq;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.isA;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests {@link PutListAttributeModel}.
+ */
+public class PutListAttributeModelTest {
+
+    /**
+     * The model to test.
+     */
+    private PutListAttributeModel model;
+
+    /**
+     * Sets up the test.
+     */
+    @Before
+    public void setUp() {
+        model = new PutListAttributeModel();
+    }
+
+    /**
+     * Test method for {@link PutListAttributeModel
+     * #execute(String, String, boolean, boolean, Request, ModelBody)}.
+     *
+     * @throws IOException If something goes wrong.
+     */
+    @Test
+    public void testExecute() throws IOException {
+        TilesContainer container = createMock(TilesContainer.class);
+        AttributeContext attributeContext = createMock(AttributeContext.class);
+        Request request = createMock(Request.class);
+        Deque<Object> composeStack = new ArrayDeque<>();
+        Map<String, Object> requestScope = new HashMap<>();
+        requestScope.put(ComposeStackUtil.COMPOSE_STACK_ATTRIBUTE_NAME, composeStack);
+        requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container);
+        ApplicationContext applicationContext = createMock(ApplicationContext.class);
+        ModelBody modelBody = createMock(ModelBody.class);
+
+        modelBody.evaluateWithoutWriting();
+        expect(request.getApplicationContext()).andReturn(applicationContext);
+        expect(request.getContext("request")).andReturn(requestScope).anyTimes();
+        expect(container.getAttributeContext(request)).andReturn(attributeContext);
+        attributeContext.putAttribute(eq("myName"), isA(ListAttribute.class), eq(false));
+
+        replay(container, attributeContext, request, modelBody);
+        model.execute("myName", "myRole", false, false, request, modelBody);
+        assertEquals(0, composeStack.size());
+        verify(container, attributeContext, request, modelBody);
+    }
+
+}
diff --git a/plugins/tiles/src/test/java/org/apache/tiles/template/SetCurrentContainerModelTest.java b/plugins/tiles/src/test/java/org/apache/tiles/template/SetCurrentContainerModelTest.java
new file mode 100644
index 000000000..2ecda504f
--- /dev/null
+++ b/plugins/tiles/src/test/java/org/apache/tiles/template/SetCurrentContainerModelTest.java
@@ -0,0 +1,84 @@
+/*
+ * 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.template;
+
+import org.apache.tiles.api.NoSuchContainerException;
+import org.apache.tiles.api.TilesContainer;
+import org.apache.tiles.api.access.TilesAccess;
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.Request;
+import org.junit.Test;
+
+import java.util.HashMap;
+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;
+
+/**
+ * Tests {@link SetCurrentContainerModel}.
+ */
+public class SetCurrentContainerModelTest {
+
+    /**
+     * Test method for {@link SetCurrentContainerModel#execute(String, Request)}.
+     */
+    @Test
+    public void testSetCurrentContainer() {
+        Request request = createMock(Request.class);
+        ApplicationContext context = createMock(ApplicationContext.class);
+        TilesContainer container = createMock(TilesContainer.class);
+        Map<String, Object> attribs = new HashMap<>();
+        attribs.put("myKey", container);
+        Map<String, Object> requestScope = new HashMap<>();
+
+        expect(context.getApplicationScope()).andReturn(attribs).anyTimes();
+        expect(request.getContext("request")).andReturn(requestScope);
+        expect(request.getApplicationContext()).andReturn(context);
+        replay(request, context, container);
+        SetCurrentContainerModel model = new SetCurrentContainerModel();
+        model.execute("myKey", request);
+        assertEquals(container, requestScope.get(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME));
+        verify(request, context, container);
+    }
+
+    /**
+     * Test method for {@link SetCurrentContainerModel#execute(String, Request)}.
+     */
+    @Test(expected = NoSuchContainerException.class)
+    public void testSetCurrentContainerException() {
+        Request request = createMock(Request.class);
+        ApplicationContext context = createMock(ApplicationContext.class);
+        Map<String, Object> attribs = new HashMap<>();
+
+        expect(request.getApplicationContext()).andReturn(context);
+        expect(context.getApplicationScope()).andReturn(attribs).anyTimes();
+        replay(request, context);
+        try {
+            SetCurrentContainerModel model = new SetCurrentContainerModel();
+            model.execute("myKey", request);
+        } finally {
+            verify(request, context);
+        }
+    }
+
+}