/*
* Copyright 2002-2008 the original author or authors.
*
* Licensed 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.springframework.web.servlet.view;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import junit.framework.TestCase;
import org.easymock.MockControl;
import org.springframework.context.ApplicationContextException;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockServletContext;
import org.springframework.web.context.WebApplicationContext;
/**
* Tests for AbstractView. Not called AbstractViewTests as
* would otherwise be excluded by Ant build script wildcard.
*
* @author Rod Johnson
*/
public class BaseViewTests extends TestCase {
public void testRenderWithoutStaticAttributes() throws Exception {
MockControl mc = MockControl.createControl(WebApplicationContext.class);
WebApplicationContext wac = (WebApplicationContext) mc.getMock();
wac.getServletContext();
mc.setReturnValue(new MockServletContext());
mc.replay();
HttpServletRequest request = new MockHttpServletRequest();
HttpServletResponse response = new MockHttpServletResponse();
TestView tv = new TestView(request, response, wac);
// Check superclass handles duplicate init
tv.setApplicationContext(wac);
tv.setApplicationContext(wac);
Map model = new HashMap();
model.put("foo", "bar");
model.put("something", new Object());
tv.render(model, request, response);
// check it contains all
checkContainsAll(model, tv.model);
assertTrue(tv.inited);
mc.verify();
}
/**
* Test attribute passing, NOT CSV parsing.
*/
public void testRenderWithStaticAttributesNoCollision() throws Exception {
MockControl mc = MockControl.createControl(WebApplicationContext.class);
WebApplicationContext wac = (WebApplicationContext) mc.getMock();
wac.getServletContext();
mc.setReturnValue(new MockServletContext());
mc.replay();
HttpServletRequest request = new MockHttpServletRequest();
HttpServletResponse response = new MockHttpServletResponse();
TestView tv = new TestView(request, response, wac);
tv.setApplicationContext(wac);
Properties p = new Properties();
p.setProperty("foo", "bar");
p.setProperty("something", "else");
tv.setAttributes(p);
Map model = new HashMap();
model.put("one", new HashMap());
model.put("two", new Object());
tv.render(model, request, response);
// Check it contains all
checkContainsAll(model, tv.model);
checkContainsAll(p, tv.model);
assertTrue(tv.inited);
mc.verify();
}
public void testDynamicModelOverridesStaticAttributesIfCollision() throws Exception {
MockControl mc = MockControl.createControl(WebApplicationContext.class);
WebApplicationContext wac = (WebApplicationContext) mc.getMock();
wac.getServletContext();
mc.setReturnValue(new MockServletContext());
mc.replay();
HttpServletRequest request = new MockHttpServletRequest();
HttpServletResponse response = new MockHttpServletResponse();
TestView tv = new TestView(request, response, wac);
tv.setApplicationContext(wac);
Properties p = new Properties();
p.setProperty("one", "bar");
p.setProperty("something", "else");
tv.setAttributes(p);
Map model = new HashMap();
model.put("one", new HashMap());
model.put("two", new Object());
tv.render(model, request, response);
// Check it contains all
checkContainsAll(model, tv.model);
assertTrue(tv.model.size() == 3);
// will have old something from properties
assertTrue(tv.model.get("something").equals("else"));
assertTrue(tv.inited);
mc.verify();
}
public void testIgnoresNullAttributes() {
AbstractView v = new ConcreteView();
v.setAttributes(null);
assertTrue(v.getStaticAttributes().size() == 0);
}
/**
* Test only the CSV parsing implementation.
*/
public void testAttributeCSVParsingIgnoresNull() {
AbstractView v = new ConcreteView();
v.setAttributesCSV(null);
assertTrue(v.getStaticAttributes().size() == 0);
}
public void testAttributeCSVParsingIgnoresEmptyString() {
AbstractView v = new ConcreteView();
v.setAttributesCSV("");
assertTrue(v.getStaticAttributes().size() == 0);
}
/**
* Format is attname0={value1},attname1={value1}
*/
public void testAttributeCSVParsingValid() {
AbstractView v = new ConcreteView();
v.setAttributesCSV("foo=[bar],king=[kong]");
assertTrue(v.getStaticAttributes().size() == 2);
assertTrue(v.getStaticAttributes().get("foo").equals("bar"));
assertTrue(v.getStaticAttributes().get("king").equals("kong"));
}
public void testAttributeCSVParsingValidWithWeirdCharacters() {
AbstractView v = new ConcreteView();
String fooval = "owfie fue&3[][[[2 \n\n \r \t 8�3";
// Also tests empty value
String kingval = "";
v.setAttributesCSV("foo=(" + fooval + "),king={" + kingval + "},f1=[we]");
assertTrue(v.getStaticAttributes().size() == 3);
assertTrue(v.getStaticAttributes().get("foo").equals(fooval));
assertTrue(v.getStaticAttributes().get("king").equals(kingval));
}
public void testAttributeCSVParsingInvalid() {
AbstractView v = new ConcreteView();
try {
// No equals
v.setAttributesCSV("fweoiruiu");
fail();
}
catch (IllegalArgumentException ex) {
}
try {
// No value
v.setAttributesCSV("fweoiruiu=");
fail();
}
catch (IllegalArgumentException ex) {
}
try {
// No closing ]
v.setAttributesCSV("fweoiruiu=[");
fail();
}
catch (IllegalArgumentException ex) {
}
try {
// Second one is bogus
v.setAttributesCSV("fweoiruiu=[de],=");
fail();
}
catch (IllegalArgumentException ex) {
}
}
public void testAttributeCSVParsingIgoresTrailingComma() {
AbstractView v = new ConcreteView();
v.setAttributesCSV("foo=[de],");
assertTrue(v.getStaticAttributes().size() == 1);
}
/**
* Check that all keys in expected have same values in actual
* @param expected
* @param actual
*/
private void checkContainsAll(Map expected, Map actual) {
Set keys = expected.keySet();
for (Iterator iter = keys.iterator(); iter.hasNext();) {
String key = (String) iter.next();
//System.out.println("Checking model key " + key);
assertTrue("Value for model key '" + key + "' must match", actual.get(key) == expected.get(key));
}
}
/**
* Trivial concrete subclass we can use when we're interested only
* in CSV parsing, which doesn't require lifecycle management
*/
private class ConcreteView extends AbstractView {
// Do-nothing concrete subclass
protected void renderMergedOutputModel(Map model, HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
throw new UnsupportedOperationException();
}
}
/**
* Single threaded subclass of AbstractView to check superclass
* behaviour
*/
private class TestView extends AbstractView {
private HttpServletRequest request;
private HttpServletResponse response;
private WebApplicationContext wac;
public boolean inited;
/** Captured model in render */
public Map model;
public TestView(HttpServletRequest request, HttpServletResponse response, WebApplicationContext wac) {
this.request = request;
this.response = response;
this.wac = wac;
}
protected void renderMergedOutputModel(Map model, HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// do nothing
this.model = model;
}
/**
* @see org.springframework.context.support.ApplicationObjectSupport#initApplicationContext()
*/
protected void initApplicationContext() throws ApplicationContextException {
if (inited)
throw new RuntimeException("Already initialized");
this.inited = true;
assertTrue(getApplicationContext() == wac);
}
}
}