001 /***************************************************************************** 002 * Copyright (C) PicoContainer Organization. All rights reserved. * 003 * ------------------------------------------------------------------------- * 004 * The software in this package is published under the terms of the BSD * 005 * style license a copy of which has been included with this distribution in * 006 * the LICENSE.txt file. * 007 * * 008 * Original code by * 009 *****************************************************************************/ 010 package org.picocontainer.injectors; 011 012 import static org.junit.Assert.assertEquals; 013 import static org.junit.Assert.assertNotNull; 014 import static org.junit.Assert.assertSame; 015 import static org.junit.Assert.assertTrue; 016 import static org.picocontainer.parameters.ComponentParameter.DEFAULT; 017 018 import java.util.ArrayList; 019 import java.util.List; 020 021 import org.junit.Test; 022 import org.picocontainer.Characteristics; 023 import org.picocontainer.ComponentAdapter; 024 import org.picocontainer.ComponentFactory; 025 import org.picocontainer.DefaultPicoContainer; 026 import org.picocontainer.MutablePicoContainer; 027 import org.picocontainer.NameBinding; 028 import org.picocontainer.Parameter; 029 import org.picocontainer.behaviors.Caching; 030 import org.picocontainer.behaviors.ImplementationHiding; 031 import org.picocontainer.lifecycle.NullLifecycleStrategy; 032 import org.picocontainer.monitors.AbstractComponentMonitor; 033 import org.picocontainer.monitors.NullComponentMonitor; 034 import org.picocontainer.parameters.ConstantParameter; 035 import org.picocontainer.tck.AbstractComponentAdapterTest; 036 import org.picocontainer.testmodel.NullLifecycle; 037 import org.picocontainer.testmodel.PersonBean; 038 import org.picocontainer.testmodel.PurseBean; 039 import org.picocontainer.testmodel.SimpleTouchable; 040 import org.picocontainer.testmodel.Touchable; 041 042 043 @SuppressWarnings("serial") 044 public class SetterInjectorTestCase 045 extends AbstractComponentAdapterTest { 046 047 protected Class getComponentAdapterType() { 048 return SetterInjector.class; 049 } 050 051 protected ComponentFactory createDefaultComponentFactory() { 052 return new Caching().wrap(new SetterInjection()); 053 } 054 055 protected ComponentAdapter prepDEF_verifyWithoutDependencyWorks(MutablePicoContainer picoContainer) { 056 return new SetterInjector(PersonBean.class, PersonBean.class, new Parameter[] {new ConstantParameter( 057 "Pico Container")}, new NullComponentMonitor(), "set", false); 058 } 059 060 protected ComponentAdapter prepDEF_verifyDoesNotInstantiate(MutablePicoContainer picoContainer) { 061 picoContainer.addComponent("Pico Container"); 062 return new SetterInjector(DeadBody.class, DeadBody.class, new Parameter[] {DEFAULT}, new NullComponentMonitor(), 063 "set", false); 064 } 065 066 protected ComponentAdapter prepDEF_visitable() { 067 return new SetterInjector(PersonBean.class, PersonBean.class, new Parameter[] {new ConstantParameter( 068 "Pico Container")}, new NullComponentMonitor(), "set", false); 069 070 } 071 072 protected ComponentAdapter prepSER_isSerializable(MutablePicoContainer picoContainer) { 073 picoContainer.addComponent("Pico Container"); 074 return new SetterInjector(PersonBean.class, PersonBean.class, new Parameter[] {DEFAULT}, new NullComponentMonitor(), 075 "set", false); 076 } 077 078 protected ComponentAdapter prepSER_isXStreamSerializable(MutablePicoContainer picoContainer) { 079 return prepSER_isSerializable(picoContainer); 080 } 081 082 protected ComponentAdapter prepDEF_isAbleToTakeParameters(MutablePicoContainer picoContainer) { 083 picoContainer.addComponent("Pico Container"); 084 picoContainer.addComponent(PersonBean.class); 085 SetterInjector componentAdapter = new SetterInjector( 086 PurseBean.class, MoneyPurse.class, new Parameter[] {DEFAULT, new ConstantParameter(100.0)}, new NullComponentMonitor(), 087 "set", false); 088 return picoContainer.as(Characteristics.NO_CACHE).addAdapter(componentAdapter).getComponentAdapter(PurseBean.class, (NameBinding) null); 089 } 090 091 public static class MoneyPurse 092 extends PurseBean { 093 double money; 094 095 public double getMoney() { 096 return money; 097 } 098 099 public void setMoney(double money) { 100 this.money = money; 101 } 102 } 103 104 protected ComponentAdapter prepVER_verificationFails(MutablePicoContainer picoContainer) { 105 picoContainer.addComponent("Pico Container"); 106 picoContainer.addComponent(PersonBean.class); 107 SetterInjector componentAdapter = new SetterInjector( 108 PurseBean.class, MoneyPurse.class, new Parameter[] {DEFAULT},new NullComponentMonitor(), 109 "set", false); 110 return picoContainer.addAdapter(componentAdapter).getComponentAdapter(PurseBean.class, (NameBinding) null); 111 } 112 113 protected ComponentAdapter prepINS_createsNewInstances(MutablePicoContainer picoContainer) { 114 picoContainer.addComponent("Pico Container"); 115 return new SetterInjector(PersonBean.class, PersonBean.class, new Parameter[] {DEFAULT}, new NullComponentMonitor(), 116 "set", false); 117 } 118 119 public static class Ghost 120 extends PersonBean { 121 public Ghost() { 122 throw new VerifyError("test"); 123 } 124 } 125 126 protected ComponentAdapter prepINS_errorIsRethrown(MutablePicoContainer picoContainer) { 127 picoContainer.addComponent("Pico Container"); 128 return new SetterInjector(Ghost.class, Ghost.class, new Parameter[] {DEFAULT}, new NullComponentMonitor(), 129 "set", false); 130 } 131 132 public static class DeadBody 133 extends PersonBean { 134 public DeadBody() { 135 throw new RuntimeException("test"); 136 } 137 } 138 139 protected ComponentAdapter prepINS_runtimeExceptionIsRethrown(MutablePicoContainer picoContainer) { 140 picoContainer.addComponent("Pico Container"); 141 return new SetterInjector(DeadBody.class, DeadBody.class, new Parameter[] {DEFAULT}, new NullComponentMonitor(), 142 "set", false); 143 } 144 145 public static class HidingPersion 146 extends PersonBean { 147 public HidingPersion() throws Exception { 148 throw new Exception("test"); 149 } 150 } 151 152 protected ComponentAdapter prepINS_normalExceptionIsRethrownInsidePicoInitializationException( 153 MutablePicoContainer picoContainer) { 154 picoContainer.addComponent("Pico Container"); 155 return new SetterInjector( 156 HidingPersion.class, HidingPersion.class, new Parameter[] {DEFAULT}, new NullComponentMonitor(), 157 "set", false); 158 } 159 160 protected ComponentAdapter prepRES_dependenciesAreResolved(MutablePicoContainer picoContainer) { 161 picoContainer.addComponent("Pico Container"); 162 picoContainer.addComponent(PersonBean.class); 163 return new SetterInjector(PurseBean.class, PurseBean.class, new Parameter[] {DEFAULT}, new NullComponentMonitor(), 164 "set", false); 165 } 166 167 public static class WealthyPerson 168 extends PersonBean { 169 PurseBean purse; 170 171 public PurseBean getPurse() { 172 return purse; 173 } 174 175 public void setPurse(PurseBean purse) { 176 this.purse = purse; 177 } 178 } 179 180 protected ComponentAdapter prepRES_failingVerificationWithCyclicDependencyException(MutablePicoContainer picoContainer) { 181 picoContainer.addComponent("Pico Container"); 182 picoContainer.addComponent(PersonBean.class, WealthyPerson.class); 183 SetterInjector componentAdapter = new SetterInjector( 184 PurseBean.class, PurseBean.class, new Parameter[] {DEFAULT}, new NullComponentMonitor(), 185 "set", false); 186 return picoContainer.as(Characteristics.NO_CACHE).addAdapter(componentAdapter).getComponentAdapter(PurseBean.class, (NameBinding) null); 187 } 188 189 protected ComponentAdapter prepRES_failingInstantiationWithCyclicDependencyException(MutablePicoContainer picoContainer) { 190 picoContainer.addComponent("Pico Container"); 191 picoContainer.addComponent(PersonBean.class, WealthyPerson.class); 192 SetterInjector componentAdapter = new SetterInjector( 193 PurseBean.class, PurseBean.class, new Parameter[] {DEFAULT}, new NullComponentMonitor(), 194 "set", false); 195 return picoContainer.as(Characteristics.NO_CACHE).addAdapter(componentAdapter).getComponentAdapter(PurseBean.class, (NameBinding) null); 196 } 197 198 public static class A { 199 private B b; 200 private String string; 201 private List list; 202 203 public void setB(B b) { 204 this.b = b; 205 } 206 207 public B getB() { 208 return b; 209 } 210 211 public String getString() { 212 return string; 213 } 214 215 public void setString(String string) { 216 this.string = string; 217 } 218 219 public List getList() { 220 return list; 221 } 222 223 public void setList(List list) { 224 this.list = list; 225 } 226 } 227 228 public static class A2 { 229 private B b; 230 private String string; 231 private List list; 232 233 public void injectB(B b) { 234 this.b = b; 235 } 236 237 public B getB() { 238 return b; 239 } 240 241 public String getString() { 242 return string; 243 } 244 245 public void injectString(String string) { 246 this.string = string; 247 } 248 249 public List getList() { 250 return list; 251 } 252 253 public void injectList(List list) { 254 this.list = list; 255 } 256 } 257 258 259 public static class B { 260 } 261 262 @Test public void testAllUnsatisfiableDependenciesAreSignalled() { 263 SetterInjector aAdapter = new SetterInjector("a", A.class, Parameter.DEFAULT, new NullComponentMonitor(), 264 "set", false); 265 SetterInjector bAdapter = new SetterInjector("b", B.class, Parameter.DEFAULT, new NullComponentMonitor(), 266 "set", false); 267 268 MutablePicoContainer pico = new DefaultPicoContainer(); 269 pico.addAdapter(bAdapter); 270 pico.addAdapter(aAdapter); 271 272 try { 273 aAdapter.getComponentInstance(pico, ComponentAdapter.NOTHING.class); 274 } catch (AbstractInjector.UnsatisfiableDependenciesException e) { 275 assertTrue(e.getUnsatisfiableDependencies().contains(List.class)); 276 assertTrue(e.getUnsatisfiableDependencies().contains(String.class)); 277 } 278 } 279 280 @Test public void testAllUnsatisfiableDependenciesAreSignalled2() { 281 SetterInjector aAdapter = new SetterInjector(A2.class, A2.class, null, new NullComponentMonitor(), 282 "set", false); 283 SetterInjector bAdapter = new SetterInjector("b", B.class, null, new NullComponentMonitor(), 284 "set", false); 285 286 MutablePicoContainer pico = new DefaultPicoContainer(); 287 pico.addComponent(List.class, ArrayList.class) 288 .addComponent(String.class, "foo") 289 .addAdapter(bAdapter) 290 .addAdapter(aAdapter); 291 292 aAdapter.getComponentInstance(pico, ComponentAdapter.NOTHING.class); 293 294 assertNotNull(aAdapter); 295 296 A2 a = pico.getComponent(A2.class); 297 assertTrue(a.getList() == null); 298 assertTrue(a.getString() == null); 299 } 300 301 public static class InitBurp { 302 303 private Wind wind; 304 305 public void initWind(Wind wind) { 306 this.wind = wind; 307 } 308 } 309 310 public static class SetterBurp { 311 312 private Wind wind; 313 314 public void setWind(Wind wind) { 315 this.wind = wind; 316 } 317 } 318 319 public static class Wind { 320 321 } 322 323 @Test public void testSetterMethodInjectionToContrastWithThatBelow() { 324 325 MutablePicoContainer pico = new DefaultPicoContainer(); 326 pico.addAdapter(new SetterInjector(SetterBurp.class, SetterBurp.class, Parameter.DEFAULT, new NullComponentMonitor(), 327 "set", false)); 328 pico.addComponent(Wind.class, new Wind()); 329 SetterBurp burp = pico.getComponent(SetterBurp.class); 330 assertNotNull(burp); 331 assertNotNull(burp.wind); 332 } 333 334 @Test public void testNonSetterMethodInjection() { 335 MutablePicoContainer pico = new DefaultPicoContainer(); 336 pico.addAdapter(new SetterInjector(InitBurp.class, InitBurp.class, Parameter.DEFAULT, new NullComponentMonitor(), 337 "set", false) { 338 protected String getInjectorPrefix() { 339 return "init"; 340 } 341 }); 342 pico.addComponent(Wind.class, new Wind()); 343 InitBurp burp = pico.getComponent(InitBurp.class); 344 assertNotNull(burp); 345 assertNotNull(burp.wind); 346 } 347 348 @Test public void testNonSetterMethodInjectionWithoutOverridingSetterPrefix() { 349 MutablePicoContainer pico = new DefaultPicoContainer(); 350 pico.addAdapter(new SetterInjector(InitBurp.class, InitBurp.class, new Parameter[0], new NullComponentMonitor(), 351 "set", false)); 352 pico.addComponent(Wind.class, new Wind()); 353 InitBurp burp = pico.getComponent(InitBurp.class); 354 assertNotNull(burp); 355 assertTrue(burp.wind == null); 356 } 357 358 359 public static class C { 360 private B b; 361 private List l; 362 private final boolean asBean; 363 364 public C() { 365 asBean = true; 366 } 367 368 public C(B b) { 369 this.l = new ArrayList(); 370 this.b = b; 371 asBean = false; 372 } 373 374 public void setB(B b) { 375 this.b = b; 376 } 377 378 public B getB() { 379 return b; 380 } 381 382 public void setList(List l) { 383 this.l = l; 384 } 385 386 public List getList() { 387 return l; 388 } 389 390 public boolean instantiatedAsBean() { 391 return asBean; 392 } 393 } 394 395 @Test public void testHybridBeans() { 396 SetterInjector bAdapter = new SetterInjector("b", B.class, null, new NullComponentMonitor(), 397 "set", false); 398 SetterInjector cAdapter = new SetterInjector("c", C.class, null, new NullComponentMonitor(), 399 "set", false); 400 SetterInjector cNullAdapter = new SetterInjector("c0", C.class, null, new NullComponentMonitor(), 401 "set", false); 402 403 MutablePicoContainer pico = new DefaultPicoContainer(); 404 pico.addAdapter(bAdapter); 405 pico.addAdapter(cAdapter); 406 pico.addAdapter(cNullAdapter); 407 pico.addComponent(ArrayList.class); 408 409 C c = (C) cAdapter.getComponentInstance(pico, ComponentAdapter.NOTHING.class); 410 assertTrue(c.instantiatedAsBean()); 411 C c0 = (C) cNullAdapter.getComponentInstance(pico, ComponentAdapter.NOTHING.class); 412 assertTrue(c0.instantiatedAsBean()); 413 } 414 415 public static class Yin { 416 private Yang yang; 417 418 public void setYin(Yang yang) { 419 this.yang = yang; 420 } 421 422 public Yang getYang() { 423 return yang; 424 } 425 } 426 427 public static class Yang { 428 private Yin yin; 429 430 public void setYang(Yin yin) { 431 this.yin = yin; 432 } 433 434 public Yin getYin() { 435 return yin; 436 } 437 } 438 439 //@Test http://jira.codehaus.org/browse/PICO-188 440 public void shouldBeAbleToHandleMutualDependenciesWithSetterInjection() { 441 MutablePicoContainer pico = new DefaultPicoContainer(new Caching().wrap(new SetterInjection())); 442 443 pico.addComponent(Yin.class); 444 pico.addComponent(Yang.class); 445 446 Yin yin = pico.getComponent(Yin.class); 447 Yang yang = pico.getComponent(Yang.class); 448 449 assertSame(yin, yang.getYin()); 450 assertSame(yang, yin.getYang()); 451 } 452 453 }