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