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 org.junit.Test;
014 import org.picocontainer.Characteristics;
015 import org.picocontainer.ComponentAdapter;
016 import org.picocontainer.ComponentFactory;
017 import org.picocontainer.DefaultPicoContainer;
018 import org.picocontainer.adapters.InstanceAdapter;
019 import org.picocontainer.containers.EmptyPicoContainer;
020 import org.picocontainer.injectors.AdaptingInjection;
021 import org.picocontainer.injectors.ConstructorInjection;
022 import org.picocontainer.injectors.ConstructorInjector;
023 import org.picocontainer.lifecycle.NullLifecycleStrategy;
024 import org.picocontainer.monitors.NullComponentMonitor;
025 import org.picocontainer.tck.AbstractComponentFactoryTest;
026
027 import static org.junit.Assert.assertEquals;
028 import static org.junit.Assert.assertNotNull;
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 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 }