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 * Idea by Rachel Davies, Original code by Aslak Hellesoy and Paul Hammant *
009 *****************************************************************************/
010 package org.picocontainer;
011
012 import static org.junit.Assert.assertEquals;
013 import static org.junit.Assert.assertNotNull;
014 import static org.junit.Assert.assertNotSame;
015 import static org.junit.Assert.assertSame;
016 import static org.junit.Assert.assertTrue;
017 import static org.junit.Assert.fail;
018 import static org.picocontainer.Characteristics.CDI;
019 import static org.picocontainer.Characteristics.SDI;
020
021 import java.io.Serializable;
022 import java.io.StringWriter;
023 import java.lang.reflect.Member;
024 import java.util.ArrayList;
025 import java.util.Collection;
026 import java.util.HashMap;
027 import java.util.LinkedList;
028 import java.util.List;
029 import java.util.Map;
030 import java.util.Properties;
031
032 import org.junit.Test;
033 import org.picocontainer.behaviors.Caching;
034 import org.picocontainer.containers.EmptyPicoContainer;
035 import org.picocontainer.injectors.AbstractInjector;
036 import org.picocontainer.injectors.ConstructorInjection;
037 import org.picocontainer.injectors.ConstructorInjector;
038 import org.picocontainer.lifecycle.NullLifecycleStrategy;
039 import org.picocontainer.monitors.NullComponentMonitor;
040 import org.picocontainer.monitors.WriterComponentMonitor;
041 import org.picocontainer.tck.AbstractPicoContainerTest;
042 import org.picocontainer.testmodel.DecoratedTouchable;
043 import org.picocontainer.testmodel.DependsOnTouchable;
044 import org.picocontainer.testmodel.SimpleTouchable;
045 import org.picocontainer.testmodel.Touchable;
046
047 /**
048 * @author Aslak Hellesøy
049 * @author Paul Hammant
050 * @author Ward Cunningham
051 * @author Mauro Talevi
052 */
053 public final class DefaultPicoContainerTestCase extends
054 AbstractPicoContainerTest {
055
056 protected MutablePicoContainer createPicoContainer(PicoContainer parent) {
057 return new DefaultPicoContainer(parent);
058 }
059
060 protected Properties[] getProperties() {
061 return new Properties[0];
062 }
063
064 @Test public void testInstantiationWithNullComponentFactory() {
065 try {
066 new DefaultPicoContainer((ComponentFactory) null, null);
067 fail("NPE expected");
068 } catch (NullPointerException e) {
069 // expected
070 }
071 }
072
073 @Test public void testUpDownDependenciesCannotBeFollowed() {
074 MutablePicoContainer parent = createPicoContainer(null);
075 MutablePicoContainer child = createPicoContainer(parent);
076
077 // ComponentF -> ComponentA -> ComponentB+C
078 child.addComponent(ComponentF.class);
079 parent.addComponent(ComponentA.class);
080 child.addComponent(ComponentB.class);
081 child.addComponent(ComponentC.class);
082
083 try {
084 child.getComponent(ComponentF.class);
085 fail("Thrown "
086 + AbstractInjector.UnsatisfiableDependenciesException.class
087 .getName() + " expected");
088 } catch (final AbstractInjector.UnsatisfiableDependenciesException e) {
089 assertEquals(ComponentB.class, e.getUnsatisfiedDependencyType());
090 }
091 }
092
093 @Test public void testComponentsCanBeRemovedByInstance() {
094 MutablePicoContainer pico = createPicoContainer(null);
095 pico.addComponent(HashMap.class);
096 pico.addComponent(ArrayList.class);
097 List list = pico.getComponent(List.class);
098 pico.removeComponentByInstance(list);
099 assertEquals(1, pico.getComponentAdapters().size());
100 assertEquals(1, pico.getComponents().size());
101 assertEquals(HashMap.class, pico.getComponent(Serializable.class)
102 .getClass());
103 }
104
105 @Test public void testComponentInstancesListIsReturnedForNullType() {
106 MutablePicoContainer pico = createPicoContainer(null);
107 List componentInstances = pico.getComponents(null);
108 assertNotNull(componentInstances);
109 assertEquals(0, componentInstances.size());
110 }
111
112 @Test public void testComponentsWithCommonSupertypeWhichIsAConstructorArgumentCanBeLookedUpByConcreteType() {
113 MutablePicoContainer pico = createPicoContainer(null);
114 pico.addComponent(LinkedList.class, LinkedList.class, Parameter.ZERO);
115 pico.addComponent(ArrayList.class);
116 assertEquals(ArrayList.class, pico
117 .getComponent((Class) ArrayList.class).getClass());
118 }
119
120 /*
121 * When pico tries to resolve DecoratedTouchable it find as dependency
122 * itself and SimpleTouchable. Problem is basically the same as above. Pico
123 * should not consider self as solution.
124 *
125 * JS fixed it ( PICO-222 ) KP
126 */
127 @Test public void testUnambiguouSelfDependency() {
128 MutablePicoContainer pico = createPicoContainer(null);
129 pico.addComponent(SimpleTouchable.class);
130 pico.addComponent(DecoratedTouchable.class);
131 Touchable t = (Touchable) pico
132 .getComponent((Object) DecoratedTouchable.class);
133 assertNotNull(t);
134 }
135
136 @Test public void testPicoUsedInBuilderStyle() {
137 MutablePicoContainer pico = createPicoContainer(null);
138 Touchable t = pico.change(Characteristics.CACHE).addComponent(
139 SimpleTouchable.class).addComponent(DecoratedTouchable.class)
140 .getComponent(DecoratedTouchable.class);
141 SimpleTouchable t2 = pico.getComponent(SimpleTouchable.class);
142 assertNotNull(t);
143 assertNotNull(t2);
144 t.touch();
145 assertTrue(t2.wasTouched);
146 }
147
148 public static class Thingie {
149 public Thingie(List c) {
150 assertNotNull(c);
151 }
152 }
153
154 @Test public void testThangCanBeInstantiatedWithArrayList() {
155 MutablePicoContainer pico = new DefaultPicoContainer();
156 pico.addComponent(Thingie.class);
157 pico.addComponent(ArrayList.class);
158 assertNotNull(pico.getComponent(Thingie.class));
159 }
160
161 @Test public void testGetComponentAdaptersOfTypeNullReturnsEmptyList() {
162 DefaultPicoContainer pico = new DefaultPicoContainer();
163 List adapters = pico.getComponentAdapters(null);
164 assertNotNull(adapters);
165 assertEquals(0, adapters.size());
166 }
167
168 public static class Service {
169 }
170
171 public static final class TransientComponent {
172 private final Service service;
173
174 public TransientComponent(Service service) {
175 this.service = service;
176 }
177 }
178
179 @Test public void testDefaultPicoContainerReturnsNewInstanceForEachCallWhenUsingTransientComponentAdapter() {
180
181 DefaultPicoContainer picoContainer = new DefaultPicoContainer(
182 new Caching().wrap(new ConstructorInjection()));
183
184 picoContainer.addComponent(Service.class);
185 picoContainer.as(Characteristics.NO_CACHE).addAdapter(
186 new ConstructorInjector(TransientComponent.class,
187 TransientComponent.class, null,
188 new NullComponentMonitor(),
189 new NullLifecycleStrategy(), false));
190 TransientComponent c1 = picoContainer
191 .getComponent(TransientComponent.class);
192 TransientComponent c2 = picoContainer
193 .getComponent(TransientComponent.class);
194 assertNotSame(c1, c2);
195 assertSame(c1.service, c2.service);
196 }
197
198 public static class DependsOnCollection {
199 public DependsOnCollection(Collection c) {
200 }
201 }
202
203 @Test public void testShouldProvideInfoAboutDependingWhenAmbiguityHappens() {
204 MutablePicoContainer pico = this.createPicoContainer(null);
205 pico.addComponent(new ArrayList());
206 pico.addComponent(new LinkedList());
207 pico.addComponent(DependsOnCollection.class);
208 try {
209 pico.getComponent(DependsOnCollection.class);
210 fail();
211 } catch (AbstractInjector.AmbiguousComponentResolutionException expected) {
212 String doc = DependsOnCollection.class.getName();
213 assertEquals(
214 "class "
215 + doc
216 + " needs a 'java.util.Collection' injected, but there are too many choices to inject. These:[class java.util.ArrayList, class java.util.LinkedList], refer http://picocontainer.org/ambiguous-injectable-help.html",
217 expected.getMessage());
218 }
219 }
220
221 @Test public void testInstantiationWithMonitorAndParent() {
222 StringWriter writer = new StringWriter();
223 ComponentMonitor monitor = new WriterComponentMonitor(writer);
224 DefaultPicoContainer parent = new DefaultPicoContainer();
225 DefaultPicoContainer child = new DefaultPicoContainer(monitor, parent);
226 parent.addComponent("st", SimpleTouchable.class);
227 child.addComponent("dot", DependsOnTouchable.class);
228 DependsOnTouchable dot = (DependsOnTouchable) child.getComponent("dot");
229 assertNotNull(dot);
230 assertTrue("writer not empty", writer.toString().length() > 0);
231 }
232
233 @Test public void testStartCapturedByMonitor() {
234 final StringBuffer sb = new StringBuffer();
235 DefaultPicoContainer dpc = new DefaultPicoContainer(
236 new NullComponentMonitor() {
237 public void invoking(PicoContainer container,
238 ComponentAdapter componentAdapter, Member member,
239 Object instance) {
240 sb.append(member.toString());
241 }
242 });
243 dpc.as(Characteristics.CACHE).addComponent(DefaultPicoContainer.class);
244 dpc.start();
245 assertEquals(
246 "ComponentMonitor should have been notified that the component had been started",
247 "public abstract void org.picocontainer.Startable.start()", sb
248 .toString());
249 }
250
251 public static class StartableClazz implements Startable {
252 private MutablePicoContainer _pico;
253
254 public void start() {
255 List<SimpleTouchable> cps = _pico
256 .getComponents(SimpleTouchable.class);
257 assertNotNull(cps);
258 }
259
260 public void stop() {
261 }
262
263 }
264
265 @Test public void testListComponentsOnStart() {
266
267 // This is really discouraged. Breaks basic principals of IoC -
268 // components should not refer
269 // to their containers
270 //
271 // Might be deleted in due coure, along with adaptersClone stuff in DPC
272
273 DefaultPicoContainer dpc = new DefaultPicoContainer();
274 dpc.addComponent(SimpleTouchable.class);
275 StartableClazz cl = new StartableClazz();
276 cl._pico = dpc;
277 dpc.addComponent(cl);
278 dpc.start();
279 }
280
281 @Test public void testCanChangeMonitor() {
282 StringWriter writer1 = new StringWriter();
283 ComponentMonitor monitor1 = new WriterComponentMonitor(writer1);
284 DefaultPicoContainer pico = new DefaultPicoContainer(monitor1);
285 pico.addComponent("t1", SimpleTouchable.class);
286 pico.addComponent("t3", SimpleTouchable.class);
287 Touchable t1 = (Touchable) pico.getComponent("t1");
288 assertNotNull(t1);
289 final String s = writer1.toString();
290 assertTrue("writer not empty", s.length() > 0);
291 StringWriter writer2 = new StringWriter();
292 ComponentMonitor monitor2 = new WriterComponentMonitor(writer2);
293 pico.changeMonitor(monitor2);
294 pico.addComponent("t2", SimpleTouchable.class);
295 Touchable t2 = (Touchable) pico.getComponent("t2");
296 assertNotNull(t2);
297 final String s2 = writer2.toString();
298 assertTrue("writer not empty", s2.length() > 0);
299 assertTrue("writers of same length",
300 writer1.toString().length() == writer2.toString().length());
301 Touchable t3 = (Touchable) pico.getComponent("t3");
302 assertNotNull(t3);
303 assertTrue("old writer was used", writer1.toString().length() < writer2
304 .toString().length());
305 }
306
307 @Test public void testCanChangeMonitorOfChildContainers() {
308 StringWriter writer1 = new StringWriter();
309 ComponentMonitor monitor1 = new WriterComponentMonitor(writer1);
310 DefaultPicoContainer parent = new DefaultPicoContainer();
311 DefaultPicoContainer child = new DefaultPicoContainer(monitor1);
312 parent.addChildContainer(child);
313 child.addComponent("t1", SimpleTouchable.class);
314 child.addComponent("t3", SimpleTouchable.class);
315 Touchable t1 = (Touchable) child.getComponent("t1");
316 assertNotNull(t1);
317 assertTrue("writer not empty", writer1.toString().length() > 0);
318 StringWriter writer2 = new StringWriter();
319 ComponentMonitor monitor2 = new WriterComponentMonitor(writer2);
320 parent.changeMonitor(monitor2);
321 child.addComponent("t2", SimpleTouchable.class);
322 Touchable t2 = (Touchable) child.getComponent("t2");
323 assertNotNull(t2);
324 assertTrue("writer not empty", writer2.toString().length() > 0);
325 String s1 = writer1.toString();
326 String s2 = writer2.toString();
327 assertTrue("writers of same length", s1.length() == s2.length());
328 Touchable t3 = (Touchable) child.getComponent("t3");
329 assertNotNull(t3);
330 assertTrue("old writer was used", writer1.toString().length() < writer2
331 .toString().length());
332 }
333
334 @Test public void testChangeMonitorIsIgnoredIfNotSupportingStrategy() {
335 StringWriter writer = new StringWriter();
336 ComponentMonitor monitor = new WriterComponentMonitor(writer);
337 DefaultPicoContainer parent = new DefaultPicoContainer(
338 new ComponentFactoryWithNoMonitor(
339 new ComponentAdapterWithNoMonitor(new SimpleTouchable())));
340 parent.addChildContainer(new EmptyPicoContainer());
341 parent.addComponent("t1", SimpleTouchable.class);
342 parent.changeMonitor(monitor);
343 assertTrue("writer empty", writer.toString().length() == 0);
344 }
345
346 @Test public void testCanReturnCurrentMonitorFromComponentFactory() {
347 StringWriter writer1 = new StringWriter();
348 ComponentMonitor monitor1 = new WriterComponentMonitor(writer1);
349 DefaultPicoContainer pico = new DefaultPicoContainer(monitor1);
350 assertEquals(monitor1, pico.currentMonitor());
351 StringWriter writer2 = new StringWriter();
352 ComponentMonitor monitor2 = new WriterComponentMonitor(writer2);
353 pico.changeMonitor(monitor2);
354 assertEquals(monitor2, pico.currentMonitor());
355 }
356
357 private static final class ComponentFactoryWithNoMonitor implements
358 ComponentFactory {
359 private final ComponentAdapter adapter;
360
361 public ComponentFactoryWithNoMonitor(ComponentAdapter adapter) {
362 this.adapter = adapter;
363 }
364
365 public ComponentAdapter createComponentAdapter(
366 ComponentMonitor componentMonitor,
367 LifecycleStrategy lifecycleStrategy,
368 Properties componentProperties, Object componentKey,
369 Class componentImplementation, Parameter... parameters)
370 throws PicoCompositionException {
371 return adapter;
372 }
373 }
374
375 private static final class ComponentAdapterWithNoMonitor implements
376 ComponentAdapter {
377 private final Object instance;
378
379 public ComponentAdapterWithNoMonitor(Object instance) {
380 this.instance = instance;
381 }
382
383 public Object getComponentKey() {
384 return instance.getClass();
385 }
386
387 public Class getComponentImplementation() {
388 return instance.getClass();
389 }
390
391 public Object getComponentInstance(PicoContainer container)
392 throws PicoCompositionException {
393 return instance;
394 }
395
396 public void verify(PicoContainer container)
397 throws PicoCompositionException {
398 }
399
400 public void accept(PicoVisitor visitor) {
401 }
402
403 public ComponentAdapter getDelegate() {
404 return null;
405 }
406
407 public ComponentAdapter findAdapterOfType(Class componentAdapterType) {
408 return null;
409 }
410
411 public String getDescriptor() {
412 return null;
413 }
414
415 }
416
417 @Test public void testMakeChildContainer() {
418 MutablePicoContainer parent = new DefaultPicoContainer();
419 parent.addComponent("t1", SimpleTouchable.class);
420 MutablePicoContainer child = parent.makeChildContainer();
421 Object t1 = child.getParent().getComponent("t1");
422 assertNotNull(t1);
423 assertTrue(t1 instanceof SimpleTouchable);
424 }
425
426 @Test public void testCanUseCustomLifecycleStrategyForClassRegistrations() {
427 DefaultPicoContainer dpc = new DefaultPicoContainer(
428 new FailingLifecycleStrategy(), null);
429 dpc.as(Characteristics.CACHE).addComponent(Startable.class,
430 MyStartable.class);
431 try {
432 dpc.start();
433 fail("should have barfed");
434 } catch (RuntimeException e) {
435 assertEquals("foo", e.getMessage());
436 }
437 }
438
439 @Test public void testCanUseCustomLifecycleStrategyForInstanceRegistrations() {
440 DefaultPicoContainer dpc = new DefaultPicoContainer(
441 new FailingLifecycleStrategy(), null);
442 Startable myStartable = new MyStartable();
443 dpc.addComponent(Startable.class, myStartable);
444 try {
445 dpc.start();
446 fail("should have barfed");
447 } catch (RuntimeException e) {
448 assertEquals("foo", e.getMessage());
449 }
450 }
451
452 public static class FailingLifecycleStrategy implements LifecycleStrategy {
453 public void start(Object component) {
454 throw new RuntimeException("foo");
455 }
456
457 public void stop(Object component) {
458 }
459
460 public void dispose(Object component) {
461 }
462
463 public boolean hasLifecycle(Class type) {
464 return true;
465 }
466
467 }
468
469 public static class MyStartable implements Startable {
470 public MyStartable() {
471 }
472
473 public void start() {
474 }
475
476 public void stop() {
477 }
478 }
479
480 public static interface A {
481
482 }
483
484 public static class SimpleA implements A {
485
486 }
487
488 public static class WrappingA implements A {
489 private final A wrapped;
490
491 public WrappingA(A wrapped) {
492 this.wrapped = wrapped;
493 }
494 }
495
496 @Test public void testCanRegisterTwoComponentsImplementingSameInterfaceOneWithInterfaceAsKey()
497 throws Exception {
498 MutablePicoContainer container = createPicoContainer(null);
499
500 container.addComponent(SimpleA.class);
501 container.addComponent(A.class, WrappingA.class);
502
503 container.start();
504
505 assertEquals(WrappingA.class, container.getComponent(A.class)
506 .getClass());
507 }
508
509 @Test public void testCanRegisterTwoComponentsWithSameImplementionAndDifferentKey()
510 throws Exception {
511 MutablePicoContainer container = createPicoContainer(null);
512
513 container.addComponent(SimpleA.class);
514 container.addComponent("A", SimpleA.class);
515
516 container.start();
517
518 assertNotNull(container.getComponent("A"));
519 assertNotNull(container.getComponent(SimpleA.class));
520 assertNotSame(container.getComponent("A"), container
521 .getComponent(SimpleA.class));
522 }
523
524 @Test public void testPicoCanDifferentiateBetweenNamedStringsThatWouldOtherwiseBeAmbiguous() {
525 MutablePicoContainer mpc = createPicoContainer(null);
526 mpc.addComponent("greeting", "1");
527 mpc.addComponent("message", "2");
528 mpc.as(Characteristics.USE_NAMES).addComponent(
529 PicoCompositionException.class, PicoCompositionException.class);
530 assertEquals("2", mpc.getComponent(PicoCompositionException.class)
531 .getMessage());
532 }
533
534 @Test public void testPicoCanDifferentiateBetweenNamedObjectsThatWouldOtherwiseBeAmbiguous() {
535 MutablePicoContainer mpc = createPicoContainer(null);
536 Horse dobbin = new Horse();
537 Horse redRum = new Horse();
538 mpc.addComponent("dobbin", dobbin);
539 mpc.addComponent("horse", redRum);
540 mpc.as(Characteristics.USE_NAMES).addComponent(CdiTurtle.class);
541 assertEquals(redRum, mpc.getComponent(CdiTurtle.class).horse);
542 }
543
544 @Test public void testPicoCanDifferentiateBetweenNamedIntsThatWouldOtherwiseBeAmbiguous() {
545 MutablePicoContainer mpc = createPicoContainer(null);
546 mpc.addComponent("one", 1);
547 mpc.addComponent("two", 2);
548 mpc.as(Characteristics.USE_NAMES).addComponent(NeedsTwo.class);
549 assertEquals(2, mpc.getComponent(NeedsTwo.class).two);
550 }
551
552 public static class ListComponentsInStartClass implements Startable {
553 private MutablePicoContainer _pico;
554
555 public void start() {
556 List<SimpleTouchable> cps = _pico
557 .getComponents(SimpleTouchable.class);
558 assertNotNull(cps);
559 }
560
561 public void stop() {
562 }
563
564 }
565
566 /**
567 * JIRA: PICO-295 reported by Erik Putrycz
568 */
569 @Test public void testListComponentsInStart() {
570 DefaultPicoContainer dpc = new DefaultPicoContainer();
571 dpc.addComponent(SimpleTouchable.class);
572 ListComponentsInStartClass cl = new ListComponentsInStartClass();
573 cl._pico = dpc;
574 dpc.addComponent(cl);
575 dpc.start();
576 }
577
578 public static class NeedsTwo {
579 private final int two;
580
581 public NeedsTwo(Integer two) {
582 this.two = two;
583 }
584 }
585
586 public static class Horse {
587 }
588
589 public static class CdiTurtle {
590 public final Horse horse;
591
592 public CdiTurtle(Horse horse) {
593 this.horse = horse;
594 }
595 }
596
597 public static class SdiDonkey {
598 public Horse horse;
599
600 public void setHorse(Horse horse) {
601 this.horse = horse;
602 }
603 }
604
605 public static class SdiRabbit {
606 public Horse horse;
607
608 public void setHorse(Horse horse) {
609 this.horse = horse;
610 }
611 }
612
613 @Test public void testMixingOfSDIandCDI() {
614
615 MutablePicoContainer container = createPicoContainer(null).change(
616 Characteristics.CACHE);
617 container.addComponent(Horse.class);
618 container.change(SDI);
619 container.addComponent(SdiDonkey.class);
620 container.addComponent(SdiRabbit.class);
621 container.change(CDI);
622 container.addComponent(CdiTurtle.class);
623
624 SdiDonkey donkey = container.getComponent(SdiDonkey.class);
625 SdiRabbit rabbit = container.getComponent(SdiRabbit.class);
626 CdiTurtle turtle = container.getComponent(CdiTurtle.class);
627
628 assertions(donkey, rabbit, turtle);
629 }
630
631 @Test public void testMixingOfSDIandCDIDifferently() {
632
633 MutablePicoContainer container = createPicoContainer(null).change(
634 Characteristics.CACHE);
635 container.addComponent(Horse.class);
636 container.addComponent(CdiTurtle.class);
637 container.change(SDI);
638 container.addComponent(SdiDonkey.class);
639 container.addComponent(SdiRabbit.class);
640
641 SdiDonkey donkey = container.getComponent(SdiDonkey.class);
642 SdiRabbit rabbit = container.getComponent(SdiRabbit.class);
643 CdiTurtle turtle = container.getComponent(CdiTurtle.class);
644
645 assertions(donkey, rabbit, turtle);
646 }
647
648 @Test public void testMixingOfSDIandCDIInBuilderStyle() {
649
650 MutablePicoContainer container = createPicoContainer(null).change(
651 Characteristics.CACHE);
652 container.addComponent(Horse.class).change(SDI).addComponent(
653 SdiDonkey.class).addComponent(SdiRabbit.class).change(CDI)
654 .addComponent(CdiTurtle.class);
655
656 SdiDonkey donkey = container.getComponent(SdiDonkey.class);
657 SdiRabbit rabbit = container.getComponent(SdiRabbit.class);
658 CdiTurtle turtle = container.getComponent(CdiTurtle.class);
659
660 assertions(donkey, rabbit, turtle);
661 }
662
663 private void assertions(SdiDonkey donkey, SdiRabbit rabbit, CdiTurtle turtle) {
664 assertNotNull(rabbit);
665 assertNotNull(donkey);
666 assertNotNull(turtle);
667 assertNotNull(turtle.horse);
668 assertNotNull(donkey.horse);
669 assertNotNull(rabbit.horse);
670 assertSame(donkey.horse, turtle.horse);
671 assertSame(rabbit.horse, turtle.horse);
672 }
673
674 @Test public void testMixingOfSDIandCDIWithTemporaryCharacterizations() {
675
676 MutablePicoContainer container = createPicoContainer(null).change(
677 Characteristics.CACHE);
678 container.addComponent(Horse.class);
679 container.addComponent(CdiTurtle.class);
680 container.as(SDI).addComponent(SdiDonkey.class);
681 container.as(SDI).addComponent(SdiRabbit.class);
682
683 SdiDonkey donkey = container.getComponent(SdiDonkey.class);
684 SdiRabbit rabbit = container.getComponent(SdiRabbit.class);
685 CdiTurtle turtle = container.getComponent(CdiTurtle.class);
686
687 assertions(donkey, rabbit, turtle);
688 }
689
690 @Test public void testMixingOfSDIandCDIWithTemporaryCharacterizationsDifferently() {
691
692 MutablePicoContainer container = createPicoContainer(null).change(
693 Characteristics.CACHE);
694 container.as(SDI).addComponent(SdiDonkey.class);
695 container.as(SDI).addComponent(SdiRabbit.class);
696 container.addComponent(Horse.class);
697 container.addComponent(CdiTurtle.class);
698
699 SdiDonkey donkey = container.getComponent(SdiDonkey.class);
700 SdiRabbit rabbit = container.getComponent(SdiRabbit.class);
701 CdiTurtle turtle = container.getComponent(CdiTurtle.class);
702
703 assertions(donkey, rabbit, turtle);
704 }
705
706 @Test public void testNoComponentIsMonitoredAndPotentiallyLateProvided() {
707 final String[] missingKey = new String[1];
708
709 String foo = (String) new DefaultPicoContainer(
710 new NullComponentMonitor() {
711 public Object noComponentFound(
712 MutablePicoContainer container, Object componentKey) {
713 missingKey[0] = (String) componentKey;
714 return "foo";
715 }
716 }).getComponent("missingKey");
717
718 assertNotNull(missingKey[0]);
719 assertEquals("missingKey", missingKey[0]);
720 assertEquals("foo", foo);
721
722 }
723
724 @Test public void testThatComponentCannotBeRemovedFromStartedContainer() {
725 MutablePicoContainer container = createPicoContainer(null);
726 container.addComponent(Map.class, HashMap.class);
727 container.start();
728 try {
729 container.removeComponent(Map.class);
730 fail("should have barfed");
731 } catch (PicoCompositionException e) {
732 }
733 }
734
735 @Test public void testThatSimpleStringComponentIsAddedOnlyOnce() {
736 MutablePicoContainer container = createPicoContainer(null);
737 container.addComponent("foo bar");
738 assertEquals(1, container.getComponentAdapters().size());
739 }
740
741 }