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 }