1 /****************************************************************************** 2 * Copyright (C) PicoContainer Organization. All rights reserved. * 3 * ------------------------------------------------------------------------- * 4 * The software in this package is published under the terms of the BSD * 5 * style license a copy of which has been included with this distribution in * 6 * the LICENSE.txt file. * 7 * * 8 * Idea by Rachel Davies, Original code by Aslak Hellesoy and Paul Hammant * 9 *****************************************************************************/ 10 11 package picocontainer.hierarchical; 12 13 import junit.framework.TestCase; 14 15 import java.io.Serializable; 16 import java.lang.reflect.Constructor; 17 import java.util.List; 18 import java.util.ArrayList; 19 import java.util.Arrays; 20 import java.util.Vector; 21 22 import picocontainer.testmodel.FlintstonesImpl; 23 import picocontainer.testmodel.FredImpl; 24 import picocontainer.testmodel.Wilma; 25 import picocontainer.testmodel.WilmaImpl; 26 import picocontainer.testmodel.Dictionary; 27 import picocontainer.testmodel.Webster; 28 import picocontainer.testmodel.Thesaurus; 29 import picocontainer.PicoInitializationException; 30 import picocontainer.PicoRegistrationException; 31 import picocontainer.ClassRegistrationPicoContainer; 32 import picocontainer.PicoContainer; 33 import picocontainer.ComponentFactory; 34 import picocontainer.PicoInvocationTargetInitailizationException; 35 import picocontainer.defaults.DefaultComponentFactory; 36 import picocontainer.defaults.NullContainer; 37 38 public class HierarchicalPicoContainerTestCase extends TestCase { 39 40 public void testBasicContainerAsserts() { 41 try { 42 new HierarchicalPicoContainer(new DefaultComponentFactory(), null); 43 fail("Should have had NPE)"); 44 } catch (NullPointerException npe) { 45 // expected 46 } 47 try { 48 new HierarchicalPicoContainer(null, new NullContainer()); 49 fail("Should have had NPE)"); 50 } catch (NullPointerException npe) { 51 // expected 52 } 53 } 54 55 public void testBasicRegAndStart() throws PicoInitializationException, PicoRegistrationException { 56 HierarchicalPicoContainer pico = new HierarchicalPicoContainer.Default(); 57 58 pico.registerComponent(FredImpl.class); 59 pico.registerComponent(WilmaImpl.class); 60 61 pico.instantiateComponents(); 62 63 assertEquals("There should be two comps in the container", 2, pico.getComponents().length); 64 65 assertTrue("There should have been a Fred in the container", pico.hasComponent(FredImpl.class)); 66 assertTrue("There should have been a Wilma in the container", pico.hasComponent(WilmaImpl.class)); 67 } 68 69 public void testTooFewComponents() throws PicoInitializationException, PicoRegistrationException { 70 HierarchicalPicoContainer pico = new HierarchicalPicoContainer.Default(); 71 72 pico.registerComponent(FredImpl.class); 73 74 try { 75 pico.instantiateComponents(); 76 fail("should need a wilma"); 77 } catch (UnsatisfiedDependencyStartupException e) { 78 // expected 79 assertTrue(e.getClassThatNeedsDeps() == FredImpl.class); 80 assertTrue(e.getMessage().indexOf(FredImpl.class.getName()) > 0); 81 82 } 83 } 84 85 public void testDupeImplementationsOfComponents() throws PicoInitializationException { 86 87 List messages = new ArrayList(); 88 HierarchicalPicoContainer pico = new HierarchicalPicoContainer.Default(); 89 try { 90 pico.registerComponent(List.class, messages); 91 pico.registerComponent(Dictionary.class, Webster.class); 92 pico.registerComponent(Thesaurus.class, Webster.class); 93 pico.instantiateComponents(); 94 95 assertEquals("Should only have one instance of Webster", 1, messages.size()); 96 Object dictionary = pico.getComponent(Dictionary.class); 97 Object thesaurus = pico.getComponent(Thesaurus.class); 98 assertSame("The dictionary and the thesaurus should heve been the same object", dictionary, thesaurus); 99 100 } catch (PicoRegistrationException e) { 101 fail("Should not have barfed with dupe registration"); 102 } 103 } 104 105 public void testDupeTypesWithClass() throws PicoInitializationException, PicoRegistrationException { 106 ClassRegistrationPicoContainer pico = new HierarchicalPicoContainer.Default(); 107 108 pico.registerComponent(WilmaImpl.class); 109 try { 110 pico.registerComponent(WilmaImpl.class); 111 fail("Should have barfed with dupe registration"); 112 } catch (DuplicateComponentTypeRegistrationException e) { 113 // expected 114 assertTrue(e.getDuplicateClass() == WilmaImpl.class); 115 assertTrue(e.getMessage().indexOf(WilmaImpl.class.getName()) > 0); 116 } 117 } 118 119 public void testDupeTypesWithObject() throws PicoInitializationException, PicoRegistrationException { 120 ClassRegistrationPicoContainer pico = new HierarchicalPicoContainer.Default(); 121 122 pico.registerComponent(WilmaImpl.class); 123 try { 124 pico.registerComponent(WilmaImpl.class, new WilmaImpl()); 125 fail("Should have barfed with dupe registration"); 126 } catch (DuplicateComponentTypeRegistrationException e) { 127 // expected 128 assertTrue(e.getDuplicateClass() == WilmaImpl.class); 129 assertTrue(e.getMessage().indexOf(WilmaImpl.class.getName()) > 0); 130 } 131 } 132 133 public static class DerivedWilma extends WilmaImpl { 134 public DerivedWilma() { 135 } 136 } 137 138 public void testAmbiguousHierarchy() throws PicoRegistrationException, PicoInitializationException { 139 140 HierarchicalPicoContainer pico = new HierarchicalPicoContainer.Default(); 141 142 // Register two Wilmas that Fred will be confused about 143 pico.registerComponent(WilmaImpl.class); 144 pico.registerComponent(DerivedWilma.class); 145 146 // Register a confused Fred 147 pico.registerComponent(FredImpl.class); 148 149 try { 150 pico.instantiateComponents(); 151 fail("Fred should have been confused about the two Wilmas"); 152 } catch (AmbiguousComponentResolutionException e) { 153 // expected 154 155 List ambiguous = Arrays.asList(e.getAmbiguousClasses()); 156 assertTrue(ambiguous.contains(DerivedWilma.class)); 157 assertTrue(ambiguous.contains(WilmaImpl.class)); 158 assertTrue(e.getMessage().indexOf(WilmaImpl.class.getName()) > 0); 159 assertTrue(e.getMessage().indexOf(DerivedWilma.class.getName()) > 0); 160 } 161 } 162 163 public void testRegisterComponentWithObject() throws PicoRegistrationException, PicoInitializationException { 164 HierarchicalPicoContainer pico = new HierarchicalPicoContainer.Default(); 165 166 pico.registerComponent(FredImpl.class); 167 pico.registerComponent(new WilmaImpl()); 168 169 pico.instantiateComponents(); 170 171 assertTrue("There should have been a Fred in the container", pico.hasComponent(FredImpl.class)); 172 assertTrue("There should have been a Wilma in the container", pico.hasComponent(WilmaImpl.class)); 173 } 174 175 public void testRegisterComponentWithObjectBadType() { 176 ClassRegistrationPicoContainer pico = new HierarchicalPicoContainer.Default(); 177 178 try { 179 pico.registerComponent(Serializable.class, new Object()); 180 fail("Shouldn't be able to register an Object as Serializable"); 181 } catch (PicoRegistrationException e) { 182 183 } 184 185 } 186 187 public void testComponentRegistrationMismatch() throws PicoInitializationException, PicoRegistrationException { 188 ClassRegistrationPicoContainer pico = new HierarchicalPicoContainer.Default(); 189 190 191 try { 192 pico.registerComponent(List.class, WilmaImpl.class); 193 } catch (AssignabilityRegistrationException e) { 194 // not worded in message 195 assertTrue(e.getMessage().indexOf(List.class.getName()) > 0); 196 assertTrue(e.getMessage().indexOf(WilmaImpl.class.getName()) > 0); 197 } 198 199 } 200 201 public void testMultipleArgumentConstructor() throws Throwable /* fixme */ { 202 HierarchicalPicoContainer pico = new HierarchicalPicoContainer.Default(); 203 204 pico.registerComponent(FredImpl.class); 205 pico.registerComponent(Wilma.class, WilmaImpl.class); 206 pico.registerComponent(FlintstonesImpl.class); 207 208 pico.instantiateComponents(); 209 210 assertTrue("There should have been a FlintstonesImpl in the container", pico.hasComponent(FlintstonesImpl.class)); 211 } 212 213 public void testGetComponentTypes() throws PicoRegistrationException, PicoInitializationException { 214 // ASLAK: don't declare as Impl. For IDEA jumps only 215 HierarchicalPicoContainer pico = new HierarchicalPicoContainer.Default(); 216 217 pico.registerComponent(FredImpl.class); 218 pico.registerComponent(Wilma.class, WilmaImpl.class); 219 220 // You might have thought that starting the container shouldn't be necessary 221 // just to get the types, but it is. The map holding the types->component instances 222 // doesn't receive anything until the components are instantiated. 223 pico.instantiateComponents(); 224 225 List types = Arrays.asList(pico.getComponentTypes()); 226 assertEquals("There should be 2 types", 2, types.size()); 227 assertTrue("There should be a FredImpl type", types.contains(FredImpl.class)); 228 assertTrue("There should be a Wilma type", types.contains(Wilma.class)); 229 assertTrue("There should not be a WilmaImpl type", !types.contains(WilmaImpl.class)); 230 } 231 232 public void testParentContainer() throws PicoRegistrationException, PicoInitializationException { 233 234 final Wilma wilma = new WilmaImpl(); 235 236 HierarchicalPicoContainer pico = new HierarchicalPicoContainer.WithParentContainer(new PicoContainer() { 237 public boolean hasComponent(Class componentType) { 238 return componentType == Wilma.class; 239 } 240 241 public Object getComponent(Class componentType) { 242 return componentType == Wilma.class ? wilma : null; 243 } 244 245 public Object[] getComponents() { 246 return new Object[]{wilma}; 247 } 248 249 public Class[] getComponentTypes() { 250 return new Class[]{Wilma.class}; 251 } 252 253 public void instantiateComponents() throws PicoInitializationException { 254 } 255 }); 256 257 pico.registerComponent(FredImpl.class); 258 259 pico.instantiateComponents(); 260 261 assertEquals("The parent should return 2 components (one from the parent)", 2, pico.getComponents().length); 262 assertTrue("Wilma should have been passed through the parent container", pico.hasComponent(Wilma.class)); 263 assertTrue("There should have been a FredImpl in the container", pico.hasComponent(FredImpl.class)); 264 265 } 266 267 268 269 public void testTooManyContructors() throws PicoRegistrationException, PicoInitializationException { 270 271 ClassRegistrationPicoContainer pico = new HierarchicalPicoContainer.Default(); 272 273 try { 274 pico.registerComponent(Vector.class); 275 fail("Should fail because there are more than one constructors"); 276 } catch (WrongNumberOfConstructorsRegistrationException e) { 277 assertTrue(e.getMessage().indexOf("4") > 0); //expected 278 // expected; 279 } 280 281 } 282 283 public void testRegisterAbstractShouldFail() throws PicoRegistrationException { 284 ClassRegistrationPicoContainer pico = new HierarchicalPicoContainer.Default(); 285 286 try { 287 pico.registerComponent(Runnable.class); 288 fail("Shouldn't be allowed to register abstract classes or interfaces."); 289 } catch (NotConcreteRegistrationException e) { 290 assertEquals(Runnable.class, e.getComponentImplementation()); 291 assertTrue(e.getMessage().indexOf(Runnable.class.getName()) > 0); 292 } 293 } 294 295 296 public static class A { 297 public A(B b) { 298 } 299 } 300 301 public static class B { 302 public B(C c, D d) { 303 } 304 } 305 306 public static class C { 307 public C(A a, B b) { 308 } 309 } 310 311 public static class D { 312 public D() { 313 } 314 } 315 316 public void testWithComponentFactory() throws PicoRegistrationException, PicoInitializationException { 317 final WilmaImpl wilma = new WilmaImpl(); 318 HierarchicalPicoContainer pc = new HierarchicalPicoContainer.WithComponentFactory(new ComponentFactory() { 319 public Object createComponent(Class componentType, Constructor constructor, Object[] args) { 320 return wilma; 321 } 322 }); 323 pc.registerComponent(WilmaImpl.class); 324 pc.instantiateComponents(); 325 assertEquals(pc.getComponent(WilmaImpl.class), wilma); 326 } 327 328 public static class Barney { 329 public Barney() { 330 throw new RuntimeException("Whoa!"); 331 } 332 } 333 334 public void testInvocationTargetException() throws PicoRegistrationException, PicoInitializationException { 335 HierarchicalPicoContainer pico = new HierarchicalPicoContainer.Default(); 336 pico.registerComponent(Barney.class); 337 try { 338 pico.instantiateComponents(); 339 } catch (PicoInvocationTargetInitailizationException e) { 340 assertEquals("Whoa!", e.getCause().getMessage()); 341 assertTrue(e.getMessage().indexOf("Whoa!") > 0); 342 } 343 } 344 345 public static class BamBam { 346 public BamBam() { 347 } 348 } 349 350 // TODO uncomment this and make it pass 351 private void tAestCircularDependencyShouldFail() throws PicoRegistrationException, PicoInitializationException { 352 HierarchicalPicoContainer pico = new HierarchicalPicoContainer.Default(); 353 354 // try { 355 pico.registerComponent(A.class); 356 pico.registerComponent(B.class); 357 pico.registerComponent(C.class); 358 pico.registerComponent(D.class); 359 360 pico.instantiateComponents(); 361 fail("Should have gotten a CircularDependencyRegistrationException"); 362 // } catch (CircularDependencyRegistrationException e) { 363 // ok 364 // } 365 } 366 367 interface Animal { 368 369 String getFood(); 370 } 371 372 public static class Dino implements Animal { 373 String food; 374 375 public Dino(String food) { 376 this.food = food; 377 } 378 379 public String getFood() { 380 return food; 381 } 382 } 383 384 public void testParameterCanBePassedToConstructor() throws Exception { 385 HierarchicalPicoContainer pico = new HierarchicalPicoContainer.Default(); 386 pico.registerComponent(Animal.class, Dino.class); 387 pico.addParameterToComponent(Dino.class, String.class, "bones"); 388 pico.instantiateComponents(); 389 390 Animal animal = (Animal) pico.getComponent(Animal.class); 391 assertNotNull("Component not null", animal); 392 assertEquals("bones", animal.getFood()); 393 } 394 395 public static class Dino2 extends Dino { 396 public Dino2(int number) { 397 super(String.valueOf(number)); 398 } 399 } 400 401 public void testParameterCanBePrimitive() throws Exception { 402 HierarchicalPicoContainer pico = new HierarchicalPicoContainer.Default(); 403 pico.registerComponent(Animal.class, Dino2.class); 404 pico.addParameterToComponent(Dino2.class, Integer.class, new Integer(22)); 405 pico.instantiateComponents(); 406 407 Animal animal = (Animal) pico.getComponent(Animal.class); 408 assertNotNull("Component not null", animal); 409 assertEquals("22", animal.getFood()); 410 } 411 412 public static class Dino3 extends Dino { 413 public Dino3(String a, String b) { 414 super(a + b); 415 } 416 } 417 418 public void testMultipleParametersCanBePassed() throws Exception { 419 HierarchicalPicoContainer pico = new HierarchicalPicoContainer.Default(); 420 pico.registerComponent(Animal.class, Dino3.class); 421 pico.addParameterToComponent(Dino3.class, String.class, "a"); 422 pico.addParameterToComponent(Dino3.class, String.class, "b"); 423 pico.instantiateComponents(); 424 425 Animal animal = (Animal) pico.getComponent(Animal.class); 426 assertNotNull("Component not null", animal); 427 assertEquals("ab", animal.getFood()); 428 429 } 430 431 public static class Dino4 extends Dino { 432 public Dino4(String a, int n, String b, Wilma wilma) { 433 super(a + n + b + " " + wilma.getClass().getName()); 434 } 435 } 436 437 public void testParametersCanBeMixedWithComponentsCanBePassed() throws Exception { 438 HierarchicalPicoContainer pico = new HierarchicalPicoContainer.Default(); 439 pico.registerComponent(Animal.class, Dino4.class); 440 pico.registerComponent(Wilma.class, WilmaImpl.class); 441 pico.addParameterToComponent(Dino4.class, String.class, "a"); 442 pico.addParameterToComponent(Dino4.class, Integer.class, new Integer(3)); 443 pico.addParameterToComponent(Dino4.class, String.class, "b"); 444 pico.instantiateComponents(); 445 446 Animal animal = (Animal) pico.getComponent(Animal.class); 447 assertNotNull("Component not null", animal); 448 assertEquals("a3b picocontainer.testmodel.WilmaImpl", animal.getFood()); 449 } 450 451 452 public static final class Donkey implements Animal { 453 private final Wilma wilma; 454 private final String name; 455 456 public Donkey(final Wilma wilma, final String name) { 457 this.wilma = wilma; 458 this.name = name; 459 } 460 461 public String getFood() { 462 return "tin cans"; 463 } 464 } 465 466 public static final class Monkey implements Animal { 467 public Monkey() { 468 } 469 470 public String getFood() { 471 return "bananas"; 472 } 473 } 474 475 public void testCannotMixLookupTypesWithKeyFirst() throws PicoRegistrationException { 476 //final ClassRegistrationPicoContainer pico = new HierarchicalPicoContainer.Default(); 477 //pico.registerComponent(Animal.class, Donkey.class, "donkey"); 478 //pico.registerComponent(Wilma.class, WilmaImpl.class); 479 //try { 480 //pico.registerComponent(Animal.class, Monkey.class); 481 //fail("Expected InconsistentLookupTypeRegistrationException"); 482 //} catch (InconsistentLookupTypeRegistrationException e) { 483 //} 484 } 485 public void testCannotMixLookupTypesWithTypeFirst() throws PicoRegistrationException { 486 //final PicoContainer pico = new HierarchicalPicoContainer.Default(); 487 //pico.registerComponent(Animal.class, Donkey.class); 488 //pico.registerComponent(Wilma.class, WilmaImpl.class); 489 //try { 490 //pico.registerComponent(Animal.class, Monkey.class, "monkey"); 491 //fail("Expected InconsistentLookupTypeRegistrationException"); 492 //} catch (InconsistentLookupTypeRegistrationException e) { 493 //} 494 } 495 496 public void testKeepingLookupTypesConsistentWorks() throws PicoRegistrationException { 497 //final PicoContainer pico = new HierarchicalPicoContainer.Default(); 498 //pico.registerComponent(Animal.class, Donkey.class, "donkey"); 499 //pico.registerComponent(Wilma.class, WilmaImpl.class); 500 //pico.registerComponent(Animal.class, Monkey.class, "monkey"); 501 } 502 503 public void testCanPassMultipleImplsAsArray() throws PicoRegistrationException, PicoInitializationException { 504 //final PicoContainer pico = new HierarchicalPicoContainer.Default(); 505 506 //pico.registerComponent(Animal.class, Donkey.class, "donkey"); 507 //pico.registerComponent(Animal.class, Monkey.class, "monkey"); 508 //pico.registerComponent(Wilma.class, WilmaImpl.class); 509 //pico.registerComponent(AnimalConsumer.class); 510 //pico.addParameterToComponent(Donkey.class, String.class,"neddy"); 511 512 //pico.instantiateComponents(); 513 //final Monkey monkey = (Monkey) pico.getComponent(Animal.class, "monkey"); 514 //assertNotNull(monkey); 515 //final Donkey donkey = (Donkey) pico.getComponent(Animal.class, "donkey"); 516 //assertNotNull(donkey); 517 //assertNotNull(donkey.wilma); 518 //assertEquals("neddy",donkey.name); 519 //final AnimalConsumer animalConsumer = (AnimalConsumer) pico.getComponent(AnimalConsumer.class); 520 //assertSame(monkey,animalConsumer.getAnimal("monkey")); 521 //assertSame(donkey,animalConsumer.getAnimal("donkey")); 522 } 523 524 525 public static interface I {} 526 public static class AA implements I { 527 public AA(I i) {} 528 } 529 public static class BB implements I { 530 public BB(I i) {} 531 } 532 533 public void testExtendAndDependOnSameType() throws PicoRegistrationException { 534 535 HierarchicalPicoContainer pico = new HierarchicalPicoContainer.Default(); 536 537 pico.registerComponent(AA.class); 538 pico.registerComponent(BB.class); 539 540 try { 541 pico.instantiateComponents(); 542 fail("Should have barfed"); 543 } catch (UnsatisfiedDependencyStartupException e) { 544 // Neither can be instantiated without the other. 545 } catch (PicoInitializationException e) { 546 e.printStackTrace(); //To change body of catch statement use Options | File Templates. 547 } 548 } 549 }

This page was automatically generated by Maven