001 // Copyright 2005 The Apache Software Foundation 002 // 003 // Licensed under the Apache License, Version 2.0 (the "License"); 004 // you may not use this file except in compliance with the License. 005 // You may obtain a copy of the License at 006 // 007 // http://www.apache.org/licenses/LICENSE-2.0 008 // 009 // Unless required by applicable law or agreed to in writing, software 010 // distributed under the License is distributed on an "AS IS" BASIS, 011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 012 // See the License for the specific language governing permissions and 013 // limitations under the License. 014 015 package org.apache.tapestry.bean; 016 017 import static org.easymock.EasyMock.expect; 018 019 import org.apache.hivemind.ApplicationRuntimeException; 020 import org.apache.hivemind.ClassResolver; 021 import org.apache.hivemind.Location; 022 import org.apache.hivemind.impl.DefaultClassResolver; 023 import org.apache.tapestry.BaseComponentTestCase; 024 import org.apache.tapestry.IBeanProvider; 025 import org.apache.tapestry.IComponent; 026 import org.apache.tapestry.INamespace; 027 import org.apache.tapestry.IPage; 028 import org.apache.tapestry.IRequestCycle; 029 import org.apache.tapestry.services.ClassFinder; 030 import org.apache.tapestry.services.Infrastructure; 031 import org.apache.tapestry.spec.BeanSpecification; 032 import org.apache.tapestry.spec.IBeanSpecification; 033 import org.testng.annotations.Test; 034 035 /** 036 * Tests for {@link org.apache.tapestry.bean.BeanProvider} (mostly new features added in release 037 * 4.0). 038 * 039 * @author Howard M. Lewis Ship 040 * @since 4.0 041 */ 042 @Test 043 public class TestBeanProvider extends BaseComponentTestCase 044 { 045 public static class BeanInitializerFixture extends AbstractBeanInitializer 046 { 047 private final RuntimeException _exception; 048 049 public BeanInitializerFixture(String propertyName, RuntimeException exception) 050 { 051 setPropertyName(propertyName); 052 _exception = exception; 053 } 054 055 public void setBeanProperty(IBeanProvider provider, Object bean) 056 { 057 throw _exception; 058 } 059 060 } 061 062 protected IBeanSpecification newBeanSpec() 063 { 064 return newMock(IBeanSpecification.class); 065 } 066 067 protected void trainGetClassName(IBeanSpecification spec, String className) 068 { 069 expect(spec.getClassName()).andReturn(className); 070 } 071 072 public void testResolveClassFailure() 073 { 074 ClassResolver resolver = newResolver(); 075 IPage page = newPage(); 076 IComponent component = newComponent(); 077 ClassFinder finder = newClassFinder(); 078 079 trainForConstructor(page, component, resolver, finder); 080 081 replay(); 082 083 BeanProvider bp = new BeanProvider(component); 084 085 verify(); 086 087 IBeanSpecification bs = newBeanSpec(); 088 089 trainGetClassName(bs, "org.foo.Bar"); 090 091 trainFindClass(finder, "org.foo.Bar", null); 092 093 trainGetExtendedId(component, "Fred/barney"); 094 095 Location l = newLocation(); 096 097 trainGetLocation(bs, l); 098 099 replay(); 100 101 try 102 { 103 bp.instantiateBean("wilma", bs); 104 unreachable(); 105 } 106 catch (ApplicationRuntimeException ex) 107 { 108 assertEquals( 109 "Unable to instantiate bean 'wilma' of component Fred/barney: Unable to find class org.foo.Bar within package list 'mypackage'.", 110 ex.getMessage()); 111 assertSame(component, ex.getComponent()); 112 assertSame(l, ex.getLocation()); 113 } 114 115 verify(); 116 } 117 118 public void testInstantiateBeanFailure() 119 { 120 ClassResolver resolver = newResolver(); 121 IPage page = newPage(); 122 IComponent component = newComponent(); 123 ClassFinder finder = newClassFinder(); 124 125 trainForConstructor(page, component, resolver, finder); 126 127 replay(); 128 129 BeanProvider bp = new BeanProvider(component); 130 131 verify(); 132 133 IBeanSpecification bs = newBeanSpec(); 134 135 trainGetClassName(bs, "org.foo.Bar"); 136 137 trainFindClass(finder, "org.foo.Bar", InstantiateFailureBean.class); 138 139 trainGetExtendedId(component, "Fred/barney"); 140 141 Location l = newLocation(); 142 143 trainGetLocation(bs, l); 144 145 replay(); 146 147 try 148 { 149 bp.instantiateBean("wilma", bs); 150 unreachable(); 151 } 152 catch (ApplicationRuntimeException ex) 153 { 154 assertEquals( 155 "Unable to instantiate bean 'wilma' (for component Fred/barney) as class org.apache.tapestry.bean.InstantiateFailureBean: Boom!", 156 ex.getMessage()); 157 assertSame(component, ex.getComponent()); 158 assertSame(l, ex.getLocation()); 159 } 160 161 verify(); 162 } 163 164 private void trainForConstructor(IPage page, IComponent component, ClassResolver resolver, 165 ClassFinder classFinder) 166 { 167 IRequestCycle cycle = newCycle(); 168 Infrastructure infrastructure = newMock(Infrastructure.class); 169 INamespace namespace = newMock(INamespace.class); 170 171 trainGetPage(component, page); 172 173 expect(page.getRequestCycle()).andReturn(cycle); 174 175 expect(cycle.getInfrastructure()).andReturn(infrastructure); 176 177 expect(infrastructure.getClassResolver()).andReturn(resolver); 178 179 expect(component.getNamespace()).andReturn(namespace); 180 181 expect(namespace.getPropertyValue("org.apache.tapestry.bean-class-packages")) 182 .andReturn("mypackage"); 183 184 expect(infrastructure.getClassFinder()).andReturn(classFinder); 185 } 186 187 protected ClassFinder newClassFinder() 188 { 189 return newMock(ClassFinder.class); 190 } 191 192 private ClassResolver newResolver() 193 { 194 return newMock(ClassResolver.class); 195 } 196 197 public void testInitializeFailure() 198 { 199 ClassResolver resolver = new DefaultClassResolver(); 200 IPage page = newPage(); 201 IComponent component = newComponent(); 202 ClassFinder finder = newClassFinder(); 203 204 trainForConstructor(page, component, resolver, finder); 205 206 replay(); 207 208 BeanProvider bp = new BeanProvider(component); 209 210 verify(); 211 212 String className = TargetBean.class.getName(); 213 214 trainFindClass(finder, className, TargetBean.class); 215 216 IBeanSpecification spec = new BeanSpecification(); 217 spec.setClassName(className); 218 219 RuntimeException t = new RuntimeException("Blat!"); 220 221 Location l = newLocation(); 222 223 IBeanInitializer bi = new BeanInitializerFixture("foo", t); 224 bi.setLocation(l); 225 226 spec.addInitializer(bi); 227 228 trainGetExtendedId(component, "Fred/barney"); 229 230 replay(); 231 232 try 233 { 234 bp.instantiateBean("wilma", spec); 235 unreachable(); 236 } 237 catch (ApplicationRuntimeException ex) 238 { 239 assertEquals( 240 "Error initializing property foo of bean 'wilma' (of component Fred/barney): Blat!", 241 ex.getMessage()); 242 assertSame(TargetBean.class, ex.getComponent().getClass()); 243 assertSame(l, ex.getLocation()); 244 assertSame(t, ex.getRootCause()); 245 } 246 247 } 248 249 private void trainFindClass(ClassFinder finder, String className, Class clazz) 250 { 251 expect(finder.findClass("mypackage", className)).andReturn(clazz); 252 } 253 }