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.Characteristics;
014import org.picocontainer.DefaultPicoContainer;
015import org.picocontainer.MutablePicoContainer;
016import org.picocontainer.PicoBuilder;
017import org.picocontainer.annotations.Nullable;
018import org.picocontainer.containers.EmptyPicoContainer;
019import org.picocontainer.lifecycle.NullLifecycleStrategy;
020import org.picocontainer.monitors.NullComponentMonitor;
021
022import java.lang.reflect.Method;
023import java.util.Arrays;
024import java.util.HashSet;
025
026import static junit.framework.Assert.assertNull;
027import static org.junit.Assert.assertEquals;
028import static org.junit.Assert.assertNotNull;
029import static org.junit.Assert.assertTrue;
030import static org.junit.Assert.fail;
031import static org.picocontainer.Characteristics.USE_NAMES;
032
033public class MethodInjectionTestCase {
034
035    public static interface IFoo {
036        void inject(Bar bar, Integer num);
037    }
038    public static class Foo implements IFoo {
039        private Bar bar;
040        private Integer num;
041
042        public void inject(Bar bar, Integer num) {
043            this.bar = bar;
044            this.num = num;
045        }
046    }
047
048    public static class Bar {
049        public Bar() {
050        }
051    }
052
053    @Test public void testMethodInjection() {
054        DefaultPicoContainer pico = new DefaultPicoContainer(new MethodInjection(), new NullLifecycleStrategy(), new EmptyPicoContainer());
055        pico.addComponent(123);
056        pico.addComponent(Foo.class);
057        pico.addComponent(Bar.class);
058        Foo foo = pico.getComponent(Foo.class);
059        assertNotNull(foo.bar);
060        assertNotNull(foo.num);
061        assertEquals("MethodInjector.ByMethodName[inject]-class org.picocontainer.injectors.MethodInjectionTestCase$Foo", pico.getComponentAdapter(Foo.class).toString());
062    }
063
064    @Test public void testMethodInjectionViaMethodDef() {
065        Method mthd = Foo.class.getMethods()[0];
066        DefaultPicoContainer pico = new DefaultPicoContainer(new MethodInjection(mthd), new NullLifecycleStrategy(), new EmptyPicoContainer());
067        pico.addComponent(123);
068        pico.addComponent(Foo.class);
069        pico.addComponent(new Bar());
070        Foo foo = pico.getComponent(Foo.class);
071        assertNotNull(foo.bar);
072        assertNotNull(foo.num);
073        assertEquals("MethodInjector.ByReflectionMethod["+mthd+"]-class org.picocontainer.injectors.MethodInjectionTestCase$Foo", pico.getComponentAdapter(Foo.class).toString());
074    }
075
076    @Test public void testMethodInjectionViaMethodDefViaInterface() {
077        Method mthd = IFoo.class.getMethods()[0];
078        DefaultPicoContainer pico = new DefaultPicoContainer(new MethodInjection(mthd), new NullLifecycleStrategy(), new EmptyPicoContainer());
079        pico.addComponent(123);
080        pico.addComponent(Foo.class);
081        pico.addComponent(new Bar());
082        Foo foo = pico.getComponent(Foo.class);
083        assertNotNull(foo.bar);
084        assertNotNull(foo.num);
085        assertEquals("MethodInjector.ByReflectionMethod["+mthd+"]-class org.picocontainer.injectors.MethodInjectionTestCase$Foo", pico.getComponentAdapter(Foo.class).toString());
086    }
087
088    @Test public void testMethodInjectionViaMethodName() {
089        DefaultPicoContainer pico = new DefaultPicoContainer(new MethodInjection("inject"), new NullLifecycleStrategy(), new EmptyPicoContainer());
090        pico.addComponent(123);
091        pico.addComponent(Foo.class);
092        pico.addComponent(new Bar());
093        Foo foo = pico.getComponent(Foo.class);
094        assertNotNull(foo.bar);
095        assertNotNull(foo.num);
096        assertEquals("MethodInjector.ByMethodName[inject]-class org.picocontainer.injectors.MethodInjectionTestCase$Foo", pico.getComponentAdapter(Foo.class).toString());
097    }
098
099    @Test public void testMethodInjectionSilentlyFailsSafeIfWrongMethodName() {
100        DefaultPicoContainer pico = new DefaultPicoContainer(new MethodInjection("sdjfhkjsdhf"), new NullLifecycleStrategy(), new EmptyPicoContainer());
101        pico.addComponent(123);
102        pico.addComponent(Foo.class);
103        pico.addComponent(new Bar());
104        Foo foo = pico.getComponent(Foo.class);
105        assertNull(foo.bar);
106        assertNull(foo.num);
107    }
108
109    @Test public void testMethodInjectionWorksIfMethodNameOneOfAList() {
110        DefaultPicoContainer pico = new DefaultPicoContainer(new MethodInjection("sdjfhkjsdhf", "inject"), new NullLifecycleStrategy(), new EmptyPicoContainer());
111        pico.addComponent(123);
112        pico.addComponent(Foo.class);
113        pico.addComponent(new Bar());
114        Foo foo = pico.getComponent(Foo.class);
115        assertNotNull(foo.bar);
116        assertNotNull(foo.num);
117        assertEquals("MethodInjector.ByMethodName[sdjfhkjsdhf, inject]-class org.picocontainer.injectors.MethodInjectionTestCase$Foo", pico.getComponentAdapter(Foo.class).toString());
118    }
119
120    @Test public void testCompositeMethodInjectionSilentlyFailsSafeIfWrongMethodName() {
121        DefaultPicoContainer pico = new DefaultPicoContainer(new CompositeInjection(new ConstructorInjection(), new MethodInjection("sdjfhkjsdhf")), new NullLifecycleStrategy(), new EmptyPicoContainer());
122        pico.addComponent(123);
123        pico.addComponent(Foo.class);
124        pico.addComponent(new Bar());
125        Foo foo = pico.getComponent(Foo.class);
126        assertNull(foo.bar);
127        assertNull(foo.num);
128    }
129
130
131    @Test public void testMethodInjectionViaCharacteristics() {
132        DefaultPicoContainer pico = new DefaultPicoContainer(new NullLifecycleStrategy(), new EmptyPicoContainer());
133        pico.addComponent(123);
134        pico.as(Characteristics.METHOD_INJECTION).addComponent(Foo.class);
135        pico.addComponent(Bar.class);
136        Foo foo = pico.getComponent(Foo.class);
137        assertNotNull(foo.bar);
138        assertNotNull(foo.num);
139        assertEquals("MethodInjector.ByMethodName[inject]-class org.picocontainer.injectors.MethodInjectionTestCase$Foo", pico.getComponentAdapter(Foo.class).toString());
140    }
141
142    @Test public void testMethodInjectionViaAdapter() {
143        DefaultPicoContainer pico = new DefaultPicoContainer(new MethodInjection());
144        pico.addComponent(123);
145        pico.addAdapter(new MethodInjector.ByMethodName(Foo.class, Foo.class, null, new NullComponentMonitor(), new HashSet<String>(Arrays.asList("inject")), false));
146        pico.addComponent(Bar.class);
147        Foo foo = pico.getComponent(Foo.class);
148        assertNotNull(foo.bar);
149        assertNotNull(foo.num);
150        assertEquals("MethodInjector.ByMethodName[inject]-class org.picocontainer.injectors.MethodInjectionTestCase$Foo", pico.getComponentAdapter(Foo.class).toString());
151    }
152
153    @Test public void testMethodInjectionByBuilder() {
154        MutablePicoContainer pico = new PicoBuilder().withMethodInjection().build();
155        pico.addComponent(123);
156        pico.addComponent(Foo.class);
157        pico.addComponent(Bar.class);
158        Foo foo = pico.getComponent(Foo.class);
159        assertNotNull(foo.bar);
160        assertNotNull(foo.num);
161        assertEquals("MethodInjector.ByMethodName[inject]-class org.picocontainer.injectors.MethodInjectionTestCase$Foo", pico.getComponentAdapter(Foo.class).toString());
162    }
163
164    public static class Foo2 implements IFoo {
165        private Bar bar;
166        private Integer num;
167
168        public void inject(Bar bar, @Nullable Integer num) {
169            this.bar = bar;
170            this.num = num;
171        }
172    }
173
174    @Test public void testMethodInjectionWithAllowedNullableParam() {
175        DefaultPicoContainer pico = new DefaultPicoContainer(new MethodInjection(), new NullLifecycleStrategy(), new EmptyPicoContainer());
176        pico.addComponent(Foo2.class);
177        pico.addComponent(Bar.class);
178        Foo2 foo = pico.getComponent(Foo2.class);
179        assertNotNull(foo.bar);
180        assertTrue(foo.num == null);
181        assertEquals("MethodInjector.ByMethodName[inject]-class org.picocontainer.injectors.MethodInjectionTestCase$Foo2", pico.getComponentAdapter(Foo2.class).toString());
182    }
183
184    @Test public void testMethodInjectionWithDisallowedNullableParam() {
185        DefaultPicoContainer pico = new DefaultPicoContainer(new MethodInjection());
186        pico.addComponent(Foo.class);
187        pico.addComponent(Bar.class);
188        try {
189            Foo foo = pico.getComponent(Foo.class);
190            fail("should have barfed");
191        } catch (SingleMemberInjector.ParameterCannotBeNullException e) {
192            assertEquals("num", e.getParameterName());
193            assertTrue(e.getMessage().indexOf("Parameter 1") != -1);
194            assertTrue(e.getMessage().indexOf(Foo.class.getMethods()[0].toString()) != -1);
195        }
196    }
197
198    @Test public void testMethodInjectionWithIntegerParamCanBeconvertedFromString() {
199        DefaultPicoContainer pico = new DefaultPicoContainer(new MethodInjection(), new NullLifecycleStrategy(), new EmptyPicoContainer());
200        pico.as(USE_NAMES).addComponent(Foo.class);
201        pico.addComponent(Bar.class);
202        pico.addComponent("num", "123");
203        Foo foo = pico.getComponent(Foo.class);
204        assertNotNull(foo.bar);
205        assertNotNull(foo.num);
206        assertEquals(123, (int)foo.num);
207        assertEquals("MethodInjector.ByMethodName[inject]-class org.picocontainer.injectors.MethodInjectionTestCase$Foo", pico.getComponentAdapter(Foo.class).toString());
208    }
209
210}