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 package org.picocontainer.behaviors;
009
010 import static org.junit.Assert.assertEquals;
011 import static org.junit.Assert.assertNotNull;
012 import static org.junit.Assert.assertSame;
013 import static org.junit.Assert.fail;
014 import static org.picocontainer.tck.MockFactory.mockeryWithCountingNamingScheme;
015
016 import org.jmock.Expectations;
017 import org.jmock.Mockery;
018 import org.jmock.integration.junit4.JMock;
019 import org.junit.Test;
020 import org.junit.runner.RunWith;
021 import org.picocontainer.ComponentAdapter;
022 import org.picocontainer.DefaultPicoContainer;
023 import org.picocontainer.LifecycleStrategy;
024 import org.picocontainer.MutablePicoContainer;
025 import org.picocontainer.PicoContainer;
026 import org.picocontainer.testmodel.SimpleTouchable;
027 import org.picocontainer.testmodel.Touchable;
028
029
030
031 /**
032 * @author Mauro Talevi
033 */
034 @RunWith(JMock.class)
035 public class CachedTestCase {
036
037 private Mockery mockery = mockeryWithCountingNamingScheme();
038
039 @Test public void testComponentIsNotStartedWhenCachedAndCanBeStarted() {
040 Cached adapter = new Cached(
041 mockComponentAdapterSupportingLifecycleStrategy(true, false, false, false, false));
042 PicoContainer pico = new DefaultPicoContainer();
043 adapter.getComponentInstance(pico, ComponentAdapter.NOTHING.class);
044 adapter.start(pico);
045 }
046
047 @Test public void testComponentCanBeStartedAgainAfterBeingStopped() {
048 Cached adapter = new Cached(
049 mockComponentAdapterSupportingLifecycleStrategy(true, true, false, false, false));
050 PicoContainer pico = new DefaultPicoContainer();
051 adapter.start(pico);
052 Object instanceAfterFirstStart = adapter.getComponentInstance(pico, ComponentAdapter.NOTHING.class);
053 adapter.stop(pico);
054 adapter.start(pico);
055 Object instanceAfterSecondStart = adapter.getComponentInstance(pico, ComponentAdapter.NOTHING.class);
056 assertSame(instanceAfterFirstStart, instanceAfterSecondStart);
057 }
058
059 @Test public void testComponentCannotBeStartedIfDisposed() {
060 Cached adapter = new Cached(
061 mockComponentAdapterSupportingLifecycleStrategy(false, false, true, true, true));
062 PicoContainer pico = new DefaultPicoContainer();
063 adapter.getComponentInstance(pico, ComponentAdapter.NOTHING.class);
064 adapter.dispose(pico);
065 try {
066 adapter.start(pico);
067 fail("IllegalStateException expected");
068 } catch (Exception e) {
069 assertEquals("'interface org.picocontainer.testmodel.Touchable' already disposed", e.getMessage());
070 }
071 }
072
073 @Test public void testComponentCannotBeDisposedIfNotInstantiated() {
074 Cached adapter = new Cached(
075 mockComponentAdapterSupportingLifecycleStrategy(false, false, false, true, false));
076 PicoContainer pico = new DefaultPicoContainer();
077 try {
078 adapter.dispose(pico);
079 // fail("IllegalStateException expected");
080 } catch (Exception e) {
081 assertEquals("'interface org.picocontainer.testmodel.Touchable' not instantiated", e.getMessage());
082 }
083 }
084
085 @Test public void testComponentCannotBeStartedIfAlreadyStarted() {
086 Cached adapter = new Cached(
087 mockComponentAdapterSupportingLifecycleStrategy(true, false, false, true, false));
088 PicoContainer pico = new DefaultPicoContainer();
089 adapter.start(pico);
090 try {
091 adapter.start(pico);
092 fail("IllegalStateException expected");
093 } catch (Exception e) {
094 assertEquals("'interface org.picocontainer.testmodel.Touchable' already started", e.getMessage());
095 }
096 }
097
098 @Test public void testComponentCannotBeStoppedIfDisposed() {
099 Cached adapter = new Cached(
100 mockComponentAdapterSupportingLifecycleStrategy(false, false, true, true, false));
101 PicoContainer pico = new DefaultPicoContainer();
102 adapter.getComponentInstance(pico, ComponentAdapter.NOTHING.class);
103 adapter.dispose(pico);
104 try {
105 adapter.stop(pico);
106 fail("IllegalStateException expected");
107 } catch (Exception e) {
108 assertEquals("'interface org.picocontainer.testmodel.Touchable' already disposed", e.getMessage());
109 }
110 }
111
112 @Test public void testComponentCannotBeStoppedIfNotInstantiated() {
113 Cached adapter = new Cached(
114 mockComponentAdapterSupportingLifecycleStrategy(false, false, false, true, false));
115 PicoContainer pico = new DefaultPicoContainer();
116 try {
117 adapter.stop(pico);
118 fail("IllegalStateException expected");
119 } catch (Exception e) {
120 assertEquals("'interface org.picocontainer.testmodel.Touchable' not instantiated", e.getMessage());
121 }
122 }
123
124 @Test public void testComponentCannotBeStoppedIfNotStarted() {
125 Cached adapter = new Cached(
126 mockComponentAdapterSupportingLifecycleStrategy(true, true, false, true, false));
127 PicoContainer pico = new DefaultPicoContainer();
128 adapter.start(pico);
129 adapter.stop(pico);
130 try {
131 adapter.stop(pico);
132 fail("IllegalStateException expected");
133 } catch (Exception e) {
134 assertEquals("'interface org.picocontainer.testmodel.Touchable' not started", e.getMessage());
135 }
136 }
137
138 @Test public void testComponentCannotBeDisposedIfAlreadyDisposed() {
139 Cached adapter = new Cached(
140 mockComponentAdapterSupportingLifecycleStrategy(true, true, true, true, false));
141 PicoContainer pico = new DefaultPicoContainer();
142 adapter.start(pico);
143 adapter.stop(pico);
144 adapter.dispose(pico);
145 try {
146 adapter.dispose(pico);
147 fail("IllegalStateException expected");
148 } catch (Exception e) {
149 assertEquals("'interface org.picocontainer.testmodel.Touchable' already disposed", e.getMessage());
150 }
151 }
152
153 @Test public void testComponentIsStoppedAndDisposedIfStartedWhenFlushed() {
154 Cached adapter = new Cached(
155 mockComponentAdapterSupportingLifecycleStrategy(true, true, true, false, false));
156 PicoContainer pico = new DefaultPicoContainer();
157 adapter.start(pico);
158 adapter.flush();
159 }
160
161 @Test public void testComponentIsNotStoppedAndDisposedWhenFlushedIfNotStarted() {
162 Cached adapter = new Cached(
163 mockComponentAdapterSupportingLifecycleStrategy(false, false, false, false, false));
164 adapter.flush();
165 }
166
167 @Test public void testComponentIsNotStoppedAndDisposedWhenFlushedIfDelegateDoesNotSupportLifecycle() {
168 Cached adapter = new Cached(
169 mockComponentAdapterNotSupportingLifecycleStrategy());
170 adapter.flush();
171 }
172
173 @Test public void testLifecycleIsIgnoredIfDelegateDoesNotSupportIt() {
174 Cached adapter = new Cached(
175 mockComponentAdapterNotSupportingLifecycleStrategy());
176 PicoContainer pico = new DefaultPicoContainer();
177 adapter.start(pico);
178 adapter.stop(pico);
179 adapter.dispose(pico);
180 }
181
182 @Test public void testCanStopAComponentThatWasNeverStartedBecauseItHasNoLifecycle() {
183 MutablePicoContainer pico = new DefaultPicoContainer();
184
185 pico.addComponent(StringBuffer.class);
186
187 pico.start();
188
189 assertNotNull(pico.getComponent(StringBuffer.class));
190
191 pico.stop();
192 pico.dispose();
193 }
194
195 private ComponentAdapter mockComponentAdapterNotSupportingLifecycleStrategy() {
196 return mockery.mock(ComponentAdapter.class);
197 }
198
199 private ComponentAdapter mockComponentAdapterSupportingLifecycleStrategy(
200 final boolean start, final boolean stop, final boolean dispose, final boolean getKey, final boolean instantiate) {
201 final boolean hasLifecycle = start || stop || dispose;
202 final ComponentAdapterSupportingLifecycleStrategy ca = mockery.mock(ComponentAdapterSupportingLifecycleStrategy.class);
203 mockery.checking(new Expectations(){{
204 if (getKey) {
205 atLeast(1).of(ca).getComponentKey();
206 will(returnValue(Touchable.class));
207 }
208 if (start) {
209 atLeast(1).of(ca).start(with(any(Touchable.class)));
210 }
211 if (stop) {
212 one(ca).stop(with(any(Touchable.class)));
213 }
214 if (dispose) {
215 one(ca).dispose(with(any(Touchable.class)));
216 }
217 if (hasLifecycle || instantiate) {
218 one(ca).getComponentInstance(with(any(PicoContainer.class)), with(same(ComponentAdapter.NOTHING.class)));
219 will(returnValue(new SimpleTouchable()));
220 }
221 one(ca).getComponentImplementation();
222 will(returnValue(SimpleTouchable.class));
223 one(ca).hasLifecycle(with(same(SimpleTouchable.class)));
224 will(returnValue(true));
225 }});
226 return ca;
227 }
228
229 public static interface ComponentAdapterSupportingLifecycleStrategy extends ComponentAdapter,
230 LifecycleStrategy {
231 }
232 }