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 }