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; 011 012import org.picocontainer.behaviors.Cached; 013 014import java.util.Map; 015 016import com.thoughtworks.xstream.XStream; 017import org.junit.Before; 018import org.junit.Test; 019import org.picocontainer.behaviors.Caching; 020import org.picocontainer.behaviors.ImplementationHiding; 021import org.picocontainer.behaviors.Locking; 022import org.picocontainer.behaviors.PropertyApplying; 023import org.picocontainer.behaviors.Synchronizing; 024import org.picocontainer.containers.EmptyPicoContainer; 025import org.picocontainer.injectors.AdaptingInjection; 026import org.picocontainer.injectors.AnnotatedFieldInjection; 027import org.picocontainer.injectors.AnnotatedMethodInjection; 028import org.picocontainer.injectors.CompositeInjection; 029import org.picocontainer.injectors.ConstructorInjection; 030import org.picocontainer.injectors.NamedFieldInjection; 031import org.picocontainer.injectors.NamedMethodInjection; 032import org.picocontainer.injectors.SetterInjection; 033import org.picocontainer.injectors.TypedFieldInjection; 034import org.picocontainer.lifecycle.JavaEE5LifecycleStrategy; 035import org.picocontainer.lifecycle.NullLifecycleStrategy; 036import org.picocontainer.lifecycle.ReflectionLifecycleStrategy; 037import org.picocontainer.lifecycle.StartableLifecycleStrategy; 038import org.picocontainer.monitors.ConsoleComponentMonitor; 039import org.picocontainer.monitors.NullComponentMonitor; 040 041import java.util.HashMap; 042import java.util.Properties; 043 044import static junit.framework.Assert.assertTrue; 045import static org.junit.Assert.assertEquals; 046import static org.junit.Assert.assertNotNull; 047import static org.junit.Assert.fail; 048import static org.picocontainer.behaviors.Behaviors.caching; 049import static org.picocontainer.behaviors.Behaviors.implementationHiding; 050import static org.picocontainer.behaviors.Behaviors.synchronizing; 051import static org.picocontainer.injectors.Injectors.SDI; 052 053@SuppressWarnings("serial") 054public 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}