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     *****************************************************************************/
010    package org.picocontainer;
011    
012    import com.thoughtworks.xstream.XStream;
013    import org.junit.Before;
014    import org.junit.Test;
015    import org.picocontainer.behaviors.Caching;
016    import org.picocontainer.behaviors.ImplementationHiding;
017    import org.picocontainer.behaviors.Locking;
018    import org.picocontainer.behaviors.PropertyApplying;
019    import org.picocontainer.behaviors.Synchronizing;
020    import org.picocontainer.containers.EmptyPicoContainer;
021    import org.picocontainer.injectors.AdaptingInjection;
022    import org.picocontainer.injectors.AnnotatedFieldInjection;
023    import org.picocontainer.injectors.AnnotatedMethodInjection;
024    import org.picocontainer.injectors.CompositeInjection;
025    import org.picocontainer.injectors.ConstructorInjection;
026    import org.picocontainer.injectors.NamedFieldInjection;
027    import org.picocontainer.injectors.NamedMethodInjection;
028    import org.picocontainer.injectors.SetterInjection;
029    import org.picocontainer.injectors.TypedFieldInjection;
030    import org.picocontainer.lifecycle.JavaEE5LifecycleStrategy;
031    import org.picocontainer.lifecycle.NullLifecycleStrategy;
032    import org.picocontainer.lifecycle.ReflectionLifecycleStrategy;
033    import org.picocontainer.lifecycle.StartableLifecycleStrategy;
034    import org.picocontainer.monitors.ConsoleComponentMonitor;
035    import org.picocontainer.monitors.NullComponentMonitor;
036    
037    import java.util.HashMap;
038    import java.util.Properties;
039    
040    import static junit.framework.Assert.assertTrue;
041    import static org.junit.Assert.assertEquals;
042    import static org.junit.Assert.fail;
043    import static org.picocontainer.behaviors.Behaviors.caching;
044    import static org.picocontainer.behaviors.Behaviors.implementationHiding;
045    import static org.picocontainer.behaviors.Behaviors.synchronizing;
046    import static org.picocontainer.injectors.Injectors.SDI;
047    
048    @SuppressWarnings("serial")
049    public class PicoBuilderTestCase {
050    
051        private XStream xs;
052        private EmptyPicoContainer parent = new EmptyPicoContainer();
053        private NullLifecycleStrategy lifecycle = new NullLifecycleStrategy();
054        private NullComponentMonitor ncm = new NullComponentMonitor();
055        private AdaptingInjection ai = new AdaptingInjection();
056    
057        @Before
058        public void setUp() throws Exception {
059            xs = new XStream();
060            xs.setMode(XStream.XPATH_ABSOLUTE_REFERENCES);
061        }
062    
063        @Test public void testDefaultHasNullComponentManagerAndNullLifecycleAndAdaptingInjection() {
064            Object actual = new PicoBuilder().build();
065            Object expected = new DefaultPicoContainer(ai, lifecycle, parent);
066            assertEquals(toXml(expected), toXml(actual));
067        }
068    
069        @Test public void testWithStartableLifecycle() {
070            Object actual = new PicoBuilder().withLifecycle().build();
071            Object expected = new DefaultPicoContainer(ai, new StartableLifecycleStrategy(ncm), parent, ncm);
072            assertEquals(toXml(expected), toXml(actual));
073        }
074    
075        public static class FooLifecycleStrategy extends NullLifecycleStrategy{
076        }
077    
078        @Test public void testWithCustomLifecycle() {
079            Object actual = new PicoBuilder().withLifecycle(FooLifecycleStrategy.class).build();
080            Object expected = new DefaultPicoContainer(ai, new FooLifecycleStrategy(), parent);
081            assertEquals(toXml(expected), toXml(actual));
082        }
083    
084        @Test public void testWithCustomLifecycle2() {
085            Object actual = new PicoBuilder().withLifecycle(new FooLifecycleStrategy()).build();
086            Object expected = new DefaultPicoContainer(ai, new FooLifecycleStrategy(), parent);
087            assertEquals(toXml(expected), toXml(actual));
088        }
089    
090        @Test public void testWithJEE5Lifecycle() {
091    
092            Object actual = new PicoBuilder().withJavaEE5Lifecycle().build();
093            Object expected = new DefaultPicoContainer(ai, new JavaEE5LifecycleStrategy(ncm), parent, ncm);
094            assertEquals(toXml(expected), toXml(actual));
095        }
096    
097        @Test public void testWithLifecycleInstance() {
098    
099            Object actual = new PicoBuilder().withLifecycle(new FooLifecycleStrategy()).build();
100            Object expected = new DefaultPicoContainer(ai, new FooLifecycleStrategy(), parent);
101            assertEquals(toXml(expected), toXml(actual));
102        }
103    
104        @Test public void testThatLastOfInstanceOrClassLifecycleIsDominant() {
105            Object actual = new PicoBuilder().withLifecycle(new FooLifecycleStrategy()).withLifecycle().build();
106            Object expected = new DefaultPicoContainer(ai, new StartableLifecycleStrategy(ncm), parent, ncm);
107            assertEquals(toXml(expected), toXml(actual));
108            actual = new PicoBuilder().withLifecycle().withLifecycle(new FooLifecycleStrategy()).build();
109            expected = new DefaultPicoContainer(ai,
110                    new FooLifecycleStrategy(), parent);
111            assertEquals(toXml(expected), toXml(actual));
112        }
113    
114    
115        @Test public void testWithReflectionLifecycle() {
116            Object actual = new PicoBuilder().withReflectionLifecycle().build();
117            Object expected = new DefaultPicoContainer(ai, new ReflectionLifecycleStrategy(ncm), parent, ncm);
118            assertEquals(toXml(expected), toXml(actual));
119        }
120    
121    
122        @Test public void testWithConsoleMonitor() {
123            Object actual = new PicoBuilder().withConsoleMonitor().build();
124            Object expected = new DefaultPicoContainer(ai, lifecycle, parent, new ConsoleComponentMonitor());
125            assertEquals(toXml(expected), toXml(actual));
126        }
127    
128        @Test public void testWithConsoleMonitorAndLifecycleUseTheSameUltimateMonitor() {
129            Object actual = new PicoBuilder().withLifecycle().withConsoleMonitor().build();
130            ConsoleComponentMonitor cm = new ConsoleComponentMonitor();
131            Object expected = new DefaultPicoContainer(ai, new StartableLifecycleStrategy(cm), parent, cm);
132            assertEquals(toXml(expected), toXml(actual));
133        }
134    
135    
136        @Test public void testWithCustomMonitorByClass() {
137            Object actual = new PicoBuilder().withMonitor(ConsoleComponentMonitor.class).build();
138            ConsoleComponentMonitor cm = new ConsoleComponentMonitor();
139            Object expected = new DefaultPicoContainer(ai, lifecycle, parent, cm);
140            assertEquals(toXml(expected), toXml(actual));
141        }
142    
143        @SuppressWarnings({ "unchecked" })
144        @Test public void testWithBogusCustomMonitorByClass() {
145            // We do unchecked assignment so we test what its really doing, and smart IDE's don't complain
146            try {
147                Class aClass = HashMap.class;
148                new PicoBuilder().withMonitor(aClass).build();
149                fail("should have barfed");
150            } catch (ClassCastException e) {
151                // expected
152            }
153        }
154    
155        @Test public void testWithImplementationHiding() {
156            Object actual = new PicoBuilder().withHiddenImplementations().build();
157            Object expected = new DefaultPicoContainer(new ImplementationHiding().wrap(ai), lifecycle, parent, ncm);
158            assertEquals(toXml(expected), toXml(actual));
159        }
160    
161        @Test public void testWithImplementationHidingInstance() {
162            Object actual = new PicoBuilder().withComponentFactory(new ImplementationHiding()).build();
163            Object expected = new DefaultPicoContainer(new ImplementationHiding().wrap(ai), lifecycle, parent, ncm);
164            assertEquals(toXml(expected), toXml(actual));
165        }
166    
167        @Test public void testWithInjectionFactoryChain() {
168            Object actual = new PicoBuilder(SDI()).withBehaviors(caching(), synchronizing(), implementationHiding()).build();
169            Object expected = new DefaultPicoContainer(new Caching().wrap(new Synchronizing()
170                    .wrap(new ImplementationHiding().wrap(new SetterInjection()))), lifecycle, parent, ncm);
171            assertEquals(toXml(expected), toXml(actual));
172        }
173    
174        public static class CustomParentcontainer extends EmptyPicoContainer {}
175    
176        @Test public void testCustomParentContainer() {
177            Object actual = new PicoBuilder(new CustomParentcontainer()).build();
178            Object expected = new DefaultPicoContainer(ai, lifecycle, new CustomParentcontainer(), ncm);
179            assertEquals(toXml(expected), toXml(actual));
180        }
181    
182        @Test public void testBogusParentContainerBehavesAsIfNotSet() {
183            Object actual = new PicoBuilder((PicoContainer)null).build();
184            Object expected = new DefaultPicoContainer(ai, lifecycle, parent, ncm);
185            assertEquals(toXml(expected), toXml(actual));
186        }
187    
188        @Test public void testParentAndChildContainersMutallyVisible() {
189            MutablePicoContainer parent = new PicoBuilder().build();
190            MutablePicoContainer actual = new PicoBuilder(parent).addChildToParent().build();
191    
192            MutablePicoContainer parentExpected = new PicoBuilder().build();
193            MutablePicoContainer expected = new DefaultPicoContainer(ai, lifecycle, parentExpected, ncm);
194            parentExpected.addChildContainer(expected); 
195    
196            assertEquals(toXml(expected), toXml(actual));
197            boolean b = parent.removeChildContainer(actual);
198            assertTrue(b);
199        }
200    
201        @Test
202        public void testParentAndChildContainersVetoedWhenParentNotMutable() {
203            try {
204                new PicoBuilder(parent).addChildToParent().build();
205                fail("should have barfed");
206            } catch (PicoCompositionException e) {
207                assertTrue(e.getMessage().contains("parent must be a MutablePicoContainer"));
208            }
209        }
210    
211        @Test public void testWithSetterInjection() {
212            Object actual = new PicoBuilder().withSetterInjection().build();
213            Object expected = new DefaultPicoContainer(new SetterInjection(), lifecycle, parent, ncm);
214            assertEquals(toXml(expected), toXml(actual));
215        }
216    
217        @Test public void testWithConstructorAndSetterInjectionMakesHiddenCompositeInjection() {
218            Object actual = new PicoBuilder().withConstructorInjection().withSetterInjection().build();
219            Object expected = new DefaultPicoContainer(
220                    new CompositeInjection(new ConstructorInjection(), new SetterInjection()), lifecycle, parent, ncm);
221            assertEquals(toXml(expected), toXml(actual));
222        }
223    
224        @Test public void testWithAnnotatedMethodDI() {
225            Object actual = new PicoBuilder().withAnnotatedMethodInjection().build();
226            Object expected = new DefaultPicoContainer(new AnnotatedMethodInjection(), lifecycle, parent, ncm);
227            assertEquals(toXml(expected), toXml(actual));
228        }
229    
230        @Test public void testWithAnnotatedFieldDI() {
231            Object actual = new PicoBuilder().withAnnotatedFieldInjection().build();
232            Object expected = new DefaultPicoContainer(new AnnotatedFieldInjection(), lifecycle, parent, ncm);
233            assertEquals(toXml(expected), toXml(actual));
234        }
235    
236        @Test public void testWithTypedFieldDI() {
237            Object actual = new PicoBuilder().withTypedFieldInjection().build();
238            Object expected = new DefaultPicoContainer(new TypedFieldInjection(), lifecycle, parent, ncm);
239            assertEquals(toXml(expected), toXml(actual));
240        }
241    
242        @Test public void testWithCtorDI() {
243            Object actual = new PicoBuilder().withConstructorInjection().build();
244            Object expected = new DefaultPicoContainer(new ConstructorInjection(), lifecycle, parent, ncm);
245            assertEquals(toXml(expected), toXml(actual));
246        }
247    
248        @Test public void testWithNamedMethodInjection() {
249            Object actual = new PicoBuilder().withNamedMethodInjection().build();
250            Object expected = new DefaultPicoContainer(new NamedMethodInjection(), lifecycle, parent, ncm);
251            assertEquals(toXml(expected), toXml(actual));
252        }
253    
254        @Test public void testWithNamedFieldInjection() {
255            Object actual = new PicoBuilder().withNamedFieldInjection().build();
256            Object expected = new DefaultPicoContainer(new NamedFieldInjection(), lifecycle, parent, ncm);
257            assertEquals(toXml(expected), toXml(actual));
258        }
259    
260        @Test public void testWithImplementationHidingAndSetterDI() {
261            Object actual = new PicoBuilder().withHiddenImplementations().withSetterInjection().build();
262            Object expected = new DefaultPicoContainer(new ImplementationHiding().wrap(new SetterInjection()),
263                    lifecycle, parent, ncm);
264            assertEquals(toXml(expected), toXml(actual));
265        }
266    
267        @Test public void testWithCachingImplementationHidingAndSetterDI() {
268            Object actual = new PicoBuilder().withCaching().withHiddenImplementations().withSetterInjection().build();
269            Object expected = new DefaultPicoContainer(new Caching().wrap(new ImplementationHiding().wrap(new SetterInjection())),
270                    lifecycle, parent, ncm);
271            assertEquals(toXml(expected), toXml(actual));
272        }
273    
274        @Test public void testWithSynchronizing() {
275            Object actual = new PicoBuilder().withSynchronizing().build();
276            Object expected = new DefaultPicoContainer(new Synchronizing().wrap(ai), lifecycle, parent, ncm);
277            assertEquals(toXml(expected), toXml(actual));
278        }
279    
280        @Test public void testWithLocking() {
281            Object actual = new PicoBuilder().withLocking().build();
282            Object expected = new DefaultPicoContainer(new Locking().wrap(ai), lifecycle, parent, ncm);
283            assertEquals(toXml(expected), toXml(actual));
284        }
285    
286        @Test public void testWithPropertyApplier() {
287            Object actual = new PicoBuilder().withPropertyApplier().build();
288            Object expected = new DefaultPicoContainer(new PropertyApplying().wrap(ai), lifecycle, parent, ncm);
289            assertEquals(toXml(expected), toXml(actual));
290        }
291    
292        //TODO - fix up to refer to SomeContainerDependency
293        @Test public void testWithCustomComponentFactory() {
294            Object actual = new PicoBuilder().withCustomContainerComponent(new SomeContainerDependency()).withComponentFactory(CustomComponentFactory.class).build();
295            Object expected = new DefaultPicoContainer(new CustomComponentFactory(new SomeContainerDependency()),
296                    lifecycle, parent, ncm);
297            assertEquals(toXml(expected), toXml(actual));
298        }
299    
300        public static class SomeContainerDependency {
301        }
302        public static class CustomComponentFactory implements ComponentFactory {
303    
304            @SuppressWarnings({ "UnusedDeclaration" })
305            public CustomComponentFactory(SomeContainerDependency someDependency) {
306            }
307    
308            public ComponentAdapter createComponentAdapter(ComponentMonitor componentMonitor,
309                                                           LifecycleStrategy lifecycleStrategy,
310                                                           Properties componentProperties,
311                                                           Object componentKey,
312                                                           Class componentImplementation,
313                                                           Parameter... parameters) throws PicoCompositionException {
314                return null;
315            }
316    
317            public void verify(PicoContainer container) {
318            }
319    
320            public void accept(PicoVisitor visitor) {
321                visitor.visitComponentFactory(this);
322            }
323        }
324    
325    
326        @Test public void testWithCustomPicoContainer() {
327            Object actual = new PicoBuilder().implementedBy(TestPicoContainer.class).build();
328            Object expected = new TestPicoContainer(ai, ncm, lifecycle, parent);
329            assertEquals(toXml(expected), toXml(actual));
330        }
331    
332    
333        public static class TestPicoContainer extends DefaultPicoContainer {
334            public TestPicoContainer(ComponentFactory componentFactory, ComponentMonitor monitor, LifecycleStrategy lifecycleStrategy, PicoContainer parent) {
335                super(componentFactory, lifecycleStrategy, parent, monitor);
336            }
337        }
338    
339        private String toXml(Object expected) {
340            return xs.toXML(expected);
341        }
342    
343    
344    }