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 * Original code by                                                          *
009 *****************************************************************************/
010package org.picocontainer.injectors;
011
012import org.junit.Test;
013import org.picocontainer.DefaultPicoContainer;
014import org.picocontainer.MutablePicoContainer;
015import org.picocontainer.PicoBuilder;
016import org.picocontainer.annotations.Inject;
017import org.picocontainer.monitors.NullComponentMonitor;
018
019import java.lang.annotation.ElementType;
020import java.lang.annotation.Retention;
021import java.lang.annotation.RetentionPolicy;
022import java.lang.annotation.Target;
023
024import static junit.framework.Assert.assertEquals;
025import static junit.framework.Assert.fail;
026import static org.junit.Assert.assertNotNull;
027import static org.junit.Assert.assertNull;
028
029public class AnnotatedFieldInjectorTestCase {
030
031    public static class Helicopter {
032        @Inject
033        private PogoStick pogo;
034
035        public Helicopter() {
036        }
037    }
038
039    public static class Helicopter2 {
040        private PogoStick pogo;
041
042        public Helicopter2() {
043        }
044    }
045
046    public static class PogoStick {
047    }
048
049    @Test
050    public void testFieldInjection() {
051        MutablePicoContainer pico = new DefaultPicoContainer();
052        pico.addAdapter(new AnnotatedFieldInjector(Helicopter.class, Helicopter.class, null,
053                new NullComponentMonitor(), Inject.class, false));
054        pico.addComponent(PogoStick.class, new PogoStick());
055        Helicopter chopper = pico.getComponent(Helicopter.class);
056        assertNotNull(chopper);
057        assertNotNull(chopper.pogo);
058    }
059
060    @Test
061    public void testFieldInjectionWithoutAnnotationDoesNotWork() {
062        MutablePicoContainer pico = new DefaultPicoContainer();
063        pico.addAdapter(new AnnotatedFieldInjector(Helicopter2.class, Helicopter2.class, null,
064                new NullComponentMonitor(), Inject.class, false));
065        pico.addComponent(PogoStick.class, new PogoStick());
066        Helicopter2 chopper = pico.getComponent(Helicopter2.class);
067        assertNotNull(chopper);
068        assertNull(chopper.pogo);
069    }
070
071    @Test
072    public void testFieldDeosNotHappenWithoutRightInjectorDoesNotWork() {
073        MutablePicoContainer pico = new DefaultPicoContainer();
074        pico.addAdapter(new SetterInjector(Helicopter.class, Helicopter.class, null,
075                new NullComponentMonitor(),
076                "set", "", false, false));
077        pico.addComponent(PogoStick.class, new PogoStick());
078        Helicopter chopper = pico.getComponent(Helicopter.class);
079        assertNotNull(chopper);
080        assertNull(chopper.pogo);
081    }
082
083    @Retention(RetentionPolicy.RUNTIME)
084    @Target(value = {ElementType.METHOD, ElementType.FIELD})
085    public @interface AlternativeInject {
086    }
087
088    public static class Helicopter3 {
089        @AlternativeInject
090        private PogoStick pogo;
091
092        public Helicopter3() {
093        }
094    }
095
096    @Test
097    public void testFieldInjectionWithAlternativeInjectionAnnotation() {
098        MutablePicoContainer pico = new DefaultPicoContainer();
099        pico.addAdapter(new AnnotatedFieldInjector(Helicopter3.class, Helicopter3.class, null,
100                new NullComponentMonitor(), AlternativeInject.class, false));
101        pico.addComponent(PogoStick.class, new PogoStick());
102        Helicopter3 chopper = pico.getComponent(Helicopter3.class);
103        assertNotNull(chopper);
104        assertNotNull(chopper.pogo);
105    }
106
107    public static abstract class A {
108        @Inject
109        protected C c;
110    }
111
112    public static class B extends A {
113    }
114
115    public static class C {
116    }
117
118    @Test
119    public void testThatSuperClassCanHaveAnnotatedFields() {
120        MutablePicoContainer container = new PicoBuilder().withAutomatic().build();
121        container.addComponent(C.class);
122        container.addComponent(B.class);
123
124        B b = container.getComponent(B.class);
125        assertNotNull(b);
126        assertNotNull(b.c);
127    }
128
129    public static abstract class A2 {
130        @Inject
131        protected D2 d2;
132    }
133
134    public static abstract class B2 extends A2 {
135    }
136
137    public static class C2 extends B2 {
138    }
139
140    public static class D2 {
141    }
142
143    @Test
144    public void testThatEvenMoreSuperClassCanHaveAnnotatedFields() {
145        MutablePicoContainer container = new PicoBuilder().withAnnotatedFieldInjection().build();
146        container.addComponent(D2.class);
147        container.addComponent(C2.class);
148
149        C2 c2 = container.getComponent(C2.class);
150        assertNotNull(c2);
151        assertNotNull(c2.d2);
152    }
153
154    @Test
155    public void testThatEvenMoreSuperClassCanHaveAnnotatedFieldsViaAdaptingInjection() {
156        MutablePicoContainer container = new PicoBuilder().build();
157        container.addComponent(D2.class);
158        container.addComponent(C2.class);
159
160        C2 c2 = container.getComponent(C2.class);
161        assertNotNull(c2);
162        assertNotNull(c2.d2);
163    }
164
165    @Test public void testFieldInjectionByTypeWhereNoMatch() {
166        MutablePicoContainer container = new PicoBuilder().withAnnotatedFieldInjection().build();
167        container.setName("parent");
168        container.addComponent(C2.class);
169        try {
170            container.getComponent(C2.class);
171            fail("should have barfed");
172        } catch (AbstractInjector.UnsatisfiableDependenciesException e) {
173            String expected = "C2 has unsatisfied dependency for fields [D2.d2] from parent:1<|";
174            String actual = e.getMessage();
175            actual = actual.replace(AnnotatedFieldInjectorTestCase.class.getName() + "$", "");
176            assertEquals(expected, actual);
177        }
178    }
179
180
181}