    001    package org.picocontainer.containers;
    002
    003    import org.junit.Test;
    004    import static org.junit.Assert.fail;
    005    import static org.junit.Assert.assertNotNull;
    006    import static org.junit.Assert.assertTrue;
    007    import static org.junit.Assert.assertEquals;
    008    import org.picocontainer.MutablePicoContainer;
    009    import org.picocontainer.testmodel.SimpleTouchable;
    010    import org.picocontainer.testmodel.DependsOnTouchable;
    011    import static org.picocontainer.BindKey.bindKey;
    012    import org.picocontainer.annotations.Bind;
    013    import org.picocontainer.injectors.AbstractInjector;
    014
    015    import java.lang.annotation.Retention;
    016    import java.lang.annotation.RetentionPolicy;
    017    import java.lang.annotation.Target;
    018    import java.lang.annotation.ElementType;
    019
    020    public class TieringPicoContainerTestCase {
    021
    022        public static class Couch {
    023        }
    024
    025        public static class TiredPerson {
    026            private Couch couchToSitOn;
    027
    028            public TiredPerson(Couch couchToSitOn) {
    029                this.couchToSitOn = couchToSitOn;
    030            }
    031        }
    032
    033        @Test
    034        public void testThatGrandparentTraversalForComponentsCanBeBlocked() {
    035            MutablePicoContainer grandparent = new TieringPicoContainer();
    036            MutablePicoContainer parent = grandparent.makeChildContainer();
    037            MutablePicoContainer child = parent.makeChildContainer();
    038            grandparent.addComponent(Couch.class);
    039            child.addComponent(TiredPerson.class);
    040
    041            TiredPerson tp = null;
    042            try {
    043                tp = child.getComponent(TiredPerson.class);
    044                fail("should have barfed");
    045            } catch (AbstractInjector.UnsatisfiableDependenciesException e) {
    046                // expected
    047            }
    048
    049        }
    050
    051        @Test
    052        public void testThatParentTraversalIsOkForTiering() {
    053            MutablePicoContainer parent = new TieringPicoContainer();
    054            MutablePicoContainer child = parent.makeChildContainer();
    055            parent.addComponent(Couch.class);
    056            child.addComponent(TiredPerson.class);
    057
    058            TiredPerson tp = child.getComponent(TiredPerson.class);
    059            assertNotNull(tp);
    060            assertNotNull(tp.couchToSitOn);
    061
    062        }
    063
    064        public static class Doctor {
    065            private TiredPerson tiredPerson;
    066
    067            public Doctor(TiredPerson tiredPerson) {
    068                this.tiredPerson = tiredPerson;
    069            }
    070        }
    071
    072        public static class TiredDoctor {
    073            private Couch couchToSitOn;
    074            private final TiredPerson tiredPerson;
    075
    076            public TiredDoctor(Couch couchToSitOn, TiredPerson tiredPerson) {
    077                this.couchToSitOn = couchToSitOn;
    078                this.tiredPerson = tiredPerson;
    079            }
    080        }
    081
    082        @Test
    083        public void testThatParentTraversalIsOnlyBlockedOneTierAtATime() {
    084            MutablePicoContainer gp = new TieringPicoContainer();
    085            MutablePicoContainer p = gp.makeChildContainer();
    086            MutablePicoContainer c = p.makeChildContainer();
    087            gp.addComponent(Couch.class);
    088            p.addComponent(TiredPerson.class);
    089            c.addComponent(Doctor.class);
    090            c.addComponent(TiredDoctor.class);
    091            Doctor d = c.getComponent(Doctor.class);
    092            assertNotNull(d);
    093            assertNotNull(d.tiredPerson);
    094            assertNotNull(d.tiredPerson.couchToSitOn);
    095            try {
    096                TiredDoctor td = c.getComponent(TiredDoctor.class);
    097                fail("should have barfed");
    098            } catch (AbstractInjector.UnsatisfiableDependenciesException e) {
    099                // expected
    100            }
    101
    102        }
    103
    104        @Retention(RetentionPolicy.RUNTIME)
    105        @Target({ElementType.FIELD, ElementType.PARAMETER})
    106        @Bind
    107        public static @interface Grouchy {}
    108
    109        public static class GrouchyTiredPerson extends TiredPerson {
    110            public GrouchyTiredPerson(Couch couchToSitOn) {
    111                super(couchToSitOn);
    112            }
    113        }
    114
    115        @Retention(RetentionPolicy.RUNTIME)
    116        @Target({ElementType.FIELD, ElementType.PARAMETER})
    117        @Bind
    118        public static @interface Polite {}
    119
    120        public static class PoliteTiredPerson extends TiredPerson {
    121            public PoliteTiredPerson(Couch couchToSitOn) {
    122                super(couchToSitOn);
    123            }
    124        }
    125
    126        public static class DiscerningDoctor {
    127            private final TiredPerson tiredPerson;
    128
    129            public DiscerningDoctor(@Polite TiredPerson tiredPerson) {
    130                this.tiredPerson = tiredPerson;
    131            }
    132        }
    133
    134        @Test
    135        public void testThatGrandparentTraversalForComponentsCanBeBlockedEvenForAnnotatedInjections() {
    136            MutablePicoContainer grandparent = new TieringPicoContainer();
    137            MutablePicoContainer parent = grandparent.makeChildContainer();
    138            MutablePicoContainer child = parent.makeChildContainer();
    139            grandparent.addComponent(Couch.class);
    140            grandparent.addComponent(bindKey(TiredPerson.class, Polite.class), PoliteTiredPerson.class);
    141            grandparent.addComponent(bindKey(TiredPerson.class, Grouchy.class), GrouchyTiredPerson.class);
    142            child.addComponent(DiscerningDoctor.class);
    143
    144            assertNotNull(grandparent.getComponent(TiredPerson.class, Polite.class));
    145            assertNotNull(grandparent.getComponent(TiredPerson.class, Grouchy.class));
    146
    147            DiscerningDoctor dd = null;
    148            try {
    149                dd = child.getComponent(DiscerningDoctor.class);
    150                fail("should have barfed");
    151            } catch (AbstractInjector.UnsatisfiableDependenciesException e) {
    152                // expected
    153            }
    154
    155        }
    156
    157        @Test
    158        public void testThatGrandparentTraversalForComponentsCanBeBlockedEvenForAnnotatedInjections2() {
    159            MutablePicoContainer grandparent = new TieringPicoContainer();
    160            grandparent.addComponent(Couch.class);
    161            grandparent.addComponent(bindKey(TiredPerson.class, Polite.class), PoliteTiredPerson.class);
    162            grandparent.addComponent(bindKey(TiredPerson.class, Grouchy.class), GrouchyTiredPerson.class);
    163            grandparent.addComponent(DiscerningDoctor.class);
    164
    165            assertNotNull(grandparent.getComponent(TiredPerson.class, Polite.class));
    166            assertNotNull(grandparent.getComponent(TiredPerson.class, Grouchy.class));
    167
    168            DiscerningDoctor dd = grandparent.getComponent(DiscerningDoctor.class);
    169            assertNotNull(dd.tiredPerson);
    170            assertTrue(dd.tiredPerson instanceof PoliteTiredPerson);
    171
    172        }
    173
    174        @Test public void testRepresentationOfContainerTree() {
    175                    TieringPicoContainer parent = new TieringPicoContainer();
    176            parent.setName("parent");
    177            TieringPicoContainer child = new TieringPicoContainer(parent);
    178            child.setName("child");
    179                    parent.addComponent("st", SimpleTouchable.class);
    180                    child.addComponent("dot", DependsOnTouchable.class);
    181            assertEquals("child:1<I<parent:1<|", child.toString());
    182        }
    183
    184
    185
    186
    187    }