/* * Copyright 2002-2016 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.bind.support; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; import java.beans.PropertyEditorSupport; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.junit.Test; import org.springframework.beans.PropertyValue; import org.springframework.beans.PropertyValues; import org.springframework.mock.web.test.MockHttpServletRequest; import org.springframework.mock.web.test.MockMultipartFile; import org.springframework.mock.web.test.MockMultipartHttpServletRequest; import org.springframework.tests.sample.beans.ITestBean; import org.springframework.tests.sample.beans.TestBean; import org.springframework.web.bind.ServletRequestParameterPropertyValues; import org.springframework.web.context.request.ServletWebRequest; import org.springframework.web.multipart.support.StringMultipartFileEditor; /** * @author Juergen Hoeller */ public class WebRequestDataBinderTests { @Test public void testBindingWithNestedObjectCreation() throws Exception { TestBean tb = new TestBean(); WebRequestDataBinder binder = new WebRequestDataBinder(tb, "person"); binder.registerCustomEditor(ITestBean.class, new PropertyEditorSupport() { @Override public void setAsText(String text) throws IllegalArgumentException { setValue(new TestBean()); } }); MockHttpServletRequest request = new MockHttpServletRequest(); request.addParameter("spouse", "someValue"); request.addParameter("spouse.name", "test"); binder.bind(new ServletWebRequest(request)); assertNotNull(tb.getSpouse()); assertEquals("test", tb.getSpouse().getName()); } @Test public void testBindingWithNestedObjectCreationThroughAutoGrow() throws Exception { TestBean tb = new TestBeanWithConcreteSpouse(); WebRequestDataBinder binder = new WebRequestDataBinder(tb, "person"); binder.setIgnoreUnknownFields(false); MockHttpServletRequest request = new MockHttpServletRequest(); request.addParameter("concreteSpouse.name", "test"); binder.bind(new ServletWebRequest(request)); assertNotNull(tb.getSpouse()); assertEquals("test", tb.getSpouse().getName()); } @Test public void testFieldPrefixCausesFieldReset() throws Exception { TestBean target = new TestBean(); WebRequestDataBinder binder = new WebRequestDataBinder(target); MockHttpServletRequest request = new MockHttpServletRequest(); request.addParameter("_postProcessed", "visible"); request.addParameter("postProcessed", "on"); binder.bind(new ServletWebRequest(request)); assertTrue(target.isPostProcessed()); request.removeParameter("postProcessed"); binder.bind(new ServletWebRequest(request)); assertFalse(target.isPostProcessed()); } @Test public void testFieldPrefixCausesFieldResetWithIgnoreUnknownFields() throws Exception { TestBean target = new TestBean(); WebRequestDataBinder binder = new WebRequestDataBinder(target); binder.setIgnoreUnknownFields(false); MockHttpServletRequest request = new MockHttpServletRequest(); request.addParameter("_postProcessed", "visible"); request.addParameter("postProcessed", "on"); binder.bind(new ServletWebRequest(request)); assertTrue(target.isPostProcessed()); request.removeParameter("postProcessed"); binder.bind(new ServletWebRequest(request)); assertFalse(target.isPostProcessed()); } @Test public void testFieldDefault() throws Exception { TestBean target = new TestBean(); WebRequestDataBinder binder = new WebRequestDataBinder(target); MockHttpServletRequest request = new MockHttpServletRequest(); request.addParameter("!postProcessed", "off"); request.addParameter("postProcessed", "on"); binder.bind(new ServletWebRequest(request)); assertTrue(target.isPostProcessed()); request.removeParameter("postProcessed"); binder.bind(new ServletWebRequest(request)); assertFalse(target.isPostProcessed()); } // SPR-13502 @Test public void testCollectionFieldsDefault() throws Exception { TestBean target = new TestBean(); target.setSomeSet(null); target.setSomeList(null); target.setSomeMap(null); WebRequestDataBinder binder = new WebRequestDataBinder(target); MockHttpServletRequest request = new MockHttpServletRequest(); request.addParameter("_someSet", "visible"); request.addParameter("_someList", "visible"); request.addParameter("_someMap", "visible"); binder.bind(new ServletWebRequest(request)); assertThat(target.getSomeSet(), notNullValue()); assertThat(target.getSomeSet(), isA(Set.class)); assertThat(target.getSomeList(), notNullValue()); assertThat(target.getSomeList(), isA(List.class)); assertThat(target.getSomeMap(), notNullValue()); assertThat(target.getSomeMap(), isA(Map.class)); } @Test public void testFieldDefaultPreemptsFieldMarker() throws Exception { TestBean target = new TestBean(); WebRequestDataBinder binder = new WebRequestDataBinder(target); MockHttpServletRequest request = new MockHttpServletRequest(); request.addParameter("!postProcessed", "on"); request.addParameter("_postProcessed", "visible"); request.addParameter("postProcessed", "on"); binder.bind(new ServletWebRequest(request)); assertTrue(target.isPostProcessed()); request.removeParameter("postProcessed"); binder.bind(new ServletWebRequest(request)); assertTrue(target.isPostProcessed()); request.removeParameter("!postProcessed"); binder.bind(new ServletWebRequest(request)); assertFalse(target.isPostProcessed()); } @Test public void testFieldDefaultWithNestedProperty() throws Exception { TestBean target = new TestBean(); target.setSpouse(new TestBean()); WebRequestDataBinder binder = new WebRequestDataBinder(target); MockHttpServletRequest request = new MockHttpServletRequest(); request.addParameter("!spouse.postProcessed", "on"); request.addParameter("_spouse.postProcessed", "visible"); request.addParameter("spouse.postProcessed", "on"); binder.bind(new ServletWebRequest(request)); assertTrue(((TestBean) target.getSpouse()).isPostProcessed()); request.removeParameter("spouse.postProcessed"); binder.bind(new ServletWebRequest(request)); assertTrue(((TestBean) target.getSpouse()).isPostProcessed()); request.removeParameter("!spouse.postProcessed"); binder.bind(new ServletWebRequest(request)); assertFalse(((TestBean) target.getSpouse()).isPostProcessed()); } @Test public void testFieldDefaultNonBoolean() throws Exception { TestBean target = new TestBean(); WebRequestDataBinder binder = new WebRequestDataBinder(target); MockHttpServletRequest request = new MockHttpServletRequest(); request.addParameter("!name", "anonymous"); request.addParameter("name", "Scott"); binder.bind(new ServletWebRequest(request)); assertEquals("Scott", target.getName()); request.removeParameter("name"); binder.bind(new ServletWebRequest(request)); assertEquals("anonymous", target.getName()); } @Test public void testWithCommaSeparatedStringArray() throws Exception { TestBean target = new TestBean(); WebRequestDataBinder binder = new WebRequestDataBinder(target); MockHttpServletRequest request = new MockHttpServletRequest(); request.addParameter("stringArray", "bar"); request.addParameter("stringArray", "abc"); request.addParameter("stringArray", "123,def"); binder.bind(new ServletWebRequest(request)); assertEquals("Expected all three items to be bound", 3, target.getStringArray().length); request.removeParameter("stringArray"); request.addParameter("stringArray", "123,def"); binder.bind(new ServletWebRequest(request)); assertEquals("Expected only 1 item to be bound", 1, target.getStringArray().length); } @Test public void testEnumBinding() { EnumHolder target = new EnumHolder(); WebRequestDataBinder binder = new WebRequestDataBinder(target); MockHttpServletRequest request = new MockHttpServletRequest(); request.addParameter("myEnum", "FOO"); binder.bind(new ServletWebRequest(request)); assertEquals(MyEnum.FOO, target.getMyEnum()); } @Test public void testMultipartFileAsString() { TestBean target = new TestBean(); WebRequestDataBinder binder = new WebRequestDataBinder(target); binder.registerCustomEditor(String.class, new StringMultipartFileEditor()); MockMultipartHttpServletRequest request = new MockMultipartHttpServletRequest(); request.addFile(new MockMultipartFile("name", "Juergen".getBytes())); binder.bind(new ServletWebRequest(request)); assertEquals("Juergen", target.getName()); } @Test public void testMultipartFileAsStringArray() { TestBean target = new TestBean(); WebRequestDataBinder binder = new WebRequestDataBinder(target); binder.registerCustomEditor(String.class, new StringMultipartFileEditor()); MockMultipartHttpServletRequest request = new MockMultipartHttpServletRequest(); request.addFile(new MockMultipartFile("stringArray", "Juergen".getBytes())); binder.bind(new ServletWebRequest(request)); assertEquals(1, target.getStringArray().length); assertEquals("Juergen", target.getStringArray()[0]); } @Test public void testMultipartFilesAsStringArray() { TestBean target = new TestBean(); WebRequestDataBinder binder = new WebRequestDataBinder(target); binder.registerCustomEditor(String.class, new StringMultipartFileEditor()); MockMultipartHttpServletRequest request = new MockMultipartHttpServletRequest(); request.addFile(new MockMultipartFile("stringArray", "Juergen".getBytes())); request.addFile(new MockMultipartFile("stringArray", "Eva".getBytes())); binder.bind(new ServletWebRequest(request)); assertEquals(2, target.getStringArray().length); assertEquals("Juergen", target.getStringArray()[0]); assertEquals("Eva", target.getStringArray()[1]); } @Test public void testNoPrefix() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); request.addParameter("forname", "Tony"); request.addParameter("surname", "Blair"); request.addParameter("age", "" + 50); ServletRequestParameterPropertyValues pvs = new ServletRequestParameterPropertyValues(request); doTestTony(pvs); } @Test public void testPrefix() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); request.addParameter("test_forname", "Tony"); request.addParameter("test_surname", "Blair"); request.addParameter("test_age", "" + 50); ServletRequestParameterPropertyValues pvs = new ServletRequestParameterPropertyValues(request); assertTrue("Didn't fidn normal when given prefix", !pvs.contains("forname")); assertTrue("Did treat prefix as normal when not given prefix", pvs.contains("test_forname")); pvs = new ServletRequestParameterPropertyValues(request, "test"); doTestTony(pvs); } /** * Must contain: forname=Tony surname=Blair age=50 */ protected void doTestTony(PropertyValues pvs) throws Exception { assertTrue("Contains 3", pvs.getPropertyValues().length == 3); assertTrue("Contains forname", pvs.contains("forname")); assertTrue("Contains surname", pvs.contains("surname")); assertTrue("Contains age", pvs.contains("age")); assertTrue("Doesn't contain tory", !pvs.contains("tory")); PropertyValue[] pvArray = pvs.getPropertyValues(); Map<String, String> m = new HashMap<>(); m.put("forname", "Tony"); m.put("surname", "Blair"); m.put("age", "50"); for (PropertyValue pv : pvArray) { Object val = m.get(pv.getName()); assertTrue("Can't have unexpected value", val != null); assertTrue("Val i string", val instanceof String); assertTrue("val matches expected", val.equals(pv.getValue())); m.remove(pv.getName()); } assertTrue("Map size is 0", m.size() == 0); } @Test public void testNoParameters() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); ServletRequestParameterPropertyValues pvs = new ServletRequestParameterPropertyValues(request); assertTrue("Found no parameters", pvs.getPropertyValues().length == 0); } @Test public void testMultipleValuesForParameter() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); String[] original = new String[] {"Tony", "Rod"}; request.addParameter("forname", original); ServletRequestParameterPropertyValues pvs = new ServletRequestParameterPropertyValues(request); assertTrue("Found 1 parameter", pvs.getPropertyValues().length == 1); assertTrue("Found array value", pvs.getPropertyValue("forname").getValue() instanceof String[]); String[] values = (String[]) pvs.getPropertyValue("forname").getValue(); assertEquals("Correct values", Arrays.asList(values), Arrays.asList(original)); } public static class EnumHolder { private MyEnum myEnum; public MyEnum getMyEnum() { return myEnum; } public void setMyEnum(MyEnum myEnum) { this.myEnum = myEnum; } } public enum MyEnum { FOO, BAR } static class TestBeanWithConcreteSpouse extends TestBean { public void setConcreteSpouse(TestBean spouse) { setSpouse(spouse); } public TestBean getConcreteSpouse() { return (TestBean) getSpouse(); } } }