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 *****************************************************************************/ 009 010 package org.picocontainer.behaviors; 011 012 013 import static org.junit.Assert.assertEquals; 014 import static org.junit.Assert.assertNotNull; 015 016 import org.junit.Test; 017 import org.picocontainer.Characteristics; 018 import org.picocontainer.ComponentAdapter; 019 import org.picocontainer.ComponentFactory; 020 import org.picocontainer.DefaultPicoContainer; 021 import org.picocontainer.adapters.InstanceAdapter; 022 import org.picocontainer.containers.EmptyPicoContainer; 023 import org.picocontainer.injectors.AdaptingInjection; 024 import org.picocontainer.injectors.ConstructorInjection; 025 import org.picocontainer.injectors.ConstructorInjector; 026 import org.picocontainer.lifecycle.NullLifecycleStrategy; 027 import org.picocontainer.monitors.NullComponentMonitor; 028 import org.picocontainer.tck.AbstractComponentFactoryTest; 029 030 031 public class ImplementationHidingTestCase extends AbstractComponentFactoryTest{ 032 033 @Test public void testAddComponentUsesImplementationHidingBehavior() { 034 DefaultPicoContainer pico = 035 new DefaultPicoContainer(new ImplementationHiding().wrap(new ConstructorInjection()), new NullLifecycleStrategy(), new EmptyPicoContainer()); 036 pico.addComponent("foo", String.class); 037 ComponentAdapter<?> foo = pico.getComponentAdapter("foo"); 038 assertEquals(HiddenImplementation.class, foo.getClass()); 039 assertEquals(ConstructorInjector.class, ((AbstractBehavior) foo).getDelegate().getClass()); 040 } 041 042 @Test public void testAddComponentUsesImplementationHidingBehaviorWithRedundantHideImplProperty() { 043 DefaultPicoContainer pico = 044 new DefaultPicoContainer(new ImplementationHiding().wrap(new ConstructorInjection()), new NullLifecycleStrategy(), new EmptyPicoContainer()); 045 pico.change(Characteristics.HIDE_IMPL).addComponent("foo", String.class); 046 ComponentAdapter<?> foo = pico.getComponentAdapter("foo"); 047 assertEquals(HiddenImplementation.class, foo.getClass()); 048 assertEquals(ConstructorInjector.class, ((AbstractBehavior) foo).getDelegate().getClass()); 049 } 050 051 @Test public void testAddComponentNoesNotUseImplementationHidingBehaviorWhenNoCachePropertyIsSpecified() { 052 DefaultPicoContainer pico = 053 new DefaultPicoContainer(new ImplementationHiding().wrap(new ConstructorInjection()), new NullLifecycleStrategy(), new EmptyPicoContainer()); 054 pico.change(Characteristics.NO_HIDE_IMPL).addComponent("foo", String.class); 055 ComponentAdapter<?> foo = pico.getComponentAdapter("foo"); 056 assertEquals(ConstructorInjector.class, foo.getClass()); 057 } 058 059 @Test public void testAddAdapterUsesImplementationHidingBehavior() { 060 DefaultPicoContainer pico = 061 new DefaultPicoContainer(new ImplementationHiding().wrap(new ConstructorInjection())); 062 pico.addAdapter(new InstanceAdapter("foo", "bar", new NullLifecycleStrategy(), new NullComponentMonitor())); 063 ComponentAdapter<?> foo = pico.getComponentAdapter("foo"); 064 assertEquals(HiddenImplementation.class, foo.getClass()); 065 assertEquals(InstanceAdapter.class, ((AbstractBehavior) foo).getDelegate().getClass()); 066 } 067 068 @Test public void testAddAdapterUsesImplementationHidingBehaviorWithRedundantHideImplProperty() { 069 DefaultPicoContainer pico = 070 new DefaultPicoContainer(new ImplementationHiding().wrap(new ConstructorInjection())); 071 pico.change(Characteristics.HIDE_IMPL).addAdapter(new InstanceAdapter("foo", "bar", new NullLifecycleStrategy(), new NullComponentMonitor())); 072 ComponentAdapter<?> foo = pico.getComponentAdapter("foo"); 073 assertEquals(HiddenImplementation.class, foo.getClass()); 074 assertEquals(InstanceAdapter.class, ((AbstractBehavior) foo).getDelegate().getClass()); 075 } 076 077 @Test public void testAddAdapterNoesNotUseImplementationHidingBehaviorWhenNoCachePropertyIsSpecified() { 078 DefaultPicoContainer pico = 079 new DefaultPicoContainer(new ImplementationHiding().wrap(new ConstructorInjection())); 080 pico.change(Characteristics.NO_HIDE_IMPL).addAdapter(new InstanceAdapter("foo", "bar", new NullLifecycleStrategy(), new NullComponentMonitor())); 081 ComponentAdapter<?> foo = pico.getComponentAdapter("foo"); 082 assertEquals(InstanceAdapter.class, foo.getClass()); 083 } 084 085 086 private final ComponentFactory implementationHidingComponentFactory = 087 new ImplementationHiding().wrap(new AdaptingInjection()); 088 089 protected ComponentFactory createComponentFactory() { 090 return implementationHidingComponentFactory; 091 } 092 093 094 public static interface NeedsStringBuilder { 095 void foo(); 096 } 097 public static class NeedsStringBuilderImpl implements NeedsStringBuilder { 098 StringBuilder sb; 099 100 public NeedsStringBuilderImpl(StringBuilder sb) { 101 this.sb = sb; 102 sb.append("<init>"); 103 } 104 public void foo() { 105 sb.append("foo()"); 106 } 107 } 108 public static class NeedsNeedsStringBuilder { 109 110 NeedsStringBuilder nsb; 111 112 public NeedsNeedsStringBuilder(NeedsStringBuilder nsb) { 113 this.nsb = nsb; 114 } 115 public void foo() { 116 nsb.foo(); 117 } 118 } 119 120 @Test public void testLazyInstantiationSideEffectWhenForceOfDelayedInstantiationOfDependantClass() { 121 DefaultPicoContainer pico = 122 new DefaultPicoContainer(new ImplementationHiding().wrap(new Caching().wrap(new ConstructorInjection()))); 123 pico.addComponent(StringBuilder.class); 124 pico.addComponent(NeedsStringBuilder.class, NeedsStringBuilderImpl.class); 125 pico.addComponent(NeedsNeedsStringBuilder.class); 126 NeedsNeedsStringBuilder nnsb = pico.getComponent(NeedsNeedsStringBuilder.class); 127 assertNotNull(nnsb); 128 StringBuilder sb = pico.getComponent(StringBuilder.class); 129 assertEquals("", sb.toString()); // not instantiated yet 130 nnsb.foo(); 131 assertEquals("<init>foo()", sb.toString()); // instantiated 132 } 133 134 //@Test public void shouldNotInstantiateForEveryMethodCall() { 135 // ... 136 //} 137 138 @Test public void shouldInstantiateForEveryMethodCall() { 139 cachingTestBody("<init>foo()<init>foo()", new ImplementationHiding()); 140 } 141 142 @Test public void shouldNotInstantiateForEveryMethodCallIfCaching() { 143 cachingTestBody("<init>foo()foo()", new ImplementationHiding().wrap(new Caching())); 144 } 145 146 @Test public void shouldInstantiateForEveryMethodCallIfCachingWrapsImplementationHidingWhichIsFutile() { 147 cachingTestBody("<init>foo()<init>foo()", new Caching().wrap(new ImplementationHiding())); 148 } 149 150 private void cachingTestBody(String expectation, ComponentFactory compFactory) { 151 DefaultPicoContainer parent = new DefaultPicoContainer(new Caching()); 152 parent.addComponent(StringBuilder.class); 153 DefaultPicoContainer pico = 154 new DefaultPicoContainer(compFactory, parent); 155 pico.addComponent(NeedsStringBuilder.class, NeedsStringBuilderImpl.class); 156 NeedsStringBuilder nsb = pico.getComponent(NeedsStringBuilder.class); 157 assertNotNull(nsb); 158 nsb.foo(); 159 nsb.foo(); 160 StringBuilder sb = pico.getComponent(StringBuilder.class); 161 assertEquals(expectation, sb.toString()); 162 } 163 164 }