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