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 010package org.picocontainer.behaviors; 011 012 013import org.junit.Test; 014import org.picocontainer.Characteristics; 015import org.picocontainer.ComponentAdapter; 016import org.picocontainer.ComponentFactory; 017import org.picocontainer.DefaultPicoContainer; 018import org.picocontainer.adapters.InstanceAdapter; 019import org.picocontainer.containers.EmptyPicoContainer; 020import org.picocontainer.injectors.AdaptingInjection; 021import org.picocontainer.injectors.ConstructorInjection; 022import org.picocontainer.injectors.ConstructorInjector; 023import org.picocontainer.lifecycle.NullLifecycleStrategy; 024import org.picocontainer.monitors.NullComponentMonitor; 025import org.picocontainer.tck.AbstractComponentFactoryTest; 026 027import static org.junit.Assert.assertEquals; 028import static org.junit.Assert.assertNotNull; 029 030 031public 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 shouldInstantiateForEveryGetComponentCall() { 135 DefaultPicoContainer parent = new DefaultPicoContainer(new Caching()); 136 parent.addComponent(StringBuilder.class); 137 DefaultPicoContainer pico = 138 new DefaultPicoContainer(new ImplementationHiding(), parent); 139 pico.addComponent(NeedsStringBuilder.class, NeedsStringBuilderImpl.class); 140 NeedsStringBuilder nsb = pico.getComponent(NeedsStringBuilder.class); 141 nsb.foo(); 142 nsb = pico.getComponent(NeedsStringBuilder.class); 143 nsb.foo(); 144 StringBuilder sb = pico.getComponent(StringBuilder.class); 145 assertEquals("<init>foo()<init>foo()", sb.toString()); 146 } 147 148 @Test public void shouldInstantiateForEveryMethodCall() { 149 cachingTestBody("<init>foo()foo()", new ImplementationHiding()); 150 } 151 152 private void cachingTestBody(String expectation, ComponentFactory compFactory) { 153 DefaultPicoContainer parent = new DefaultPicoContainer(new Caching()); 154 parent.addComponent(StringBuilder.class); 155 DefaultPicoContainer pico = 156 new DefaultPicoContainer(compFactory, parent); 157 pico.addComponent(NeedsStringBuilder.class, NeedsStringBuilderImpl.class); 158 NeedsStringBuilder nsb = pico.getComponent(NeedsStringBuilder.class); 159 assertNotNull(nsb); 160 nsb.foo(); 161 nsb.foo(); 162 StringBuilder sb = pico.getComponent(StringBuilder.class); 163 assertEquals(expectation, sb.toString()); 164 } 165 166}