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 org.jmock.Mock;
011    import org.jmock.MockObjectTestCase;
012    import org.picocontainer.ComponentAdapter;
013    import org.picocontainer.PicoContainer;
014    import org.picocontainer.MutablePicoContainer;
015    import org.picocontainer.LifecycleStrategy;
016    import org.picocontainer.DefaultPicoContainer;
017    import org.picocontainer.behaviors.CachingBehavior;
018    import org.picocontainer.testmodel.SimpleTouchable;
019    import org.picocontainer.testmodel.Touchable;
020    
021    
022    /**
023     * @author Mauro Talevi
024     * @version $Revision: $
025     */
026    public class CachingBehaviorTestCase extends MockObjectTestCase {
027    
028        public void testComponentIsNotStartedWhenCachedAndCanBeStarted() {
029            CachingBehavior adapter = new CachingBehavior(
030                    mockComponentAdapterSupportingLifecycleStrategy(true, false, false));
031            PicoContainer pico = new DefaultPicoContainer();
032            adapter.getComponentInstance(pico);
033            adapter.start(pico);
034        }
035    
036        public void testComponentCanBeStartedAgainAfterBeingStopped() {
037            CachingBehavior adapter = new CachingBehavior(
038                    mockComponentAdapterSupportingLifecycleStrategy(true, true, false));
039            PicoContainer pico = new DefaultPicoContainer();
040            adapter.start(pico);
041            Object instanceAfterFirstStart = adapter.getComponentInstance(pico);
042            adapter.stop(pico);
043            adapter.start(pico);
044            Object instanceAfterSecondStart = adapter.getComponentInstance(pico);
045            assertSame(instanceAfterFirstStart, instanceAfterSecondStart);
046        }
047    
048        public void testComponentCannotBeStartedIfDisposed() {
049            CachingBehavior adapter = new CachingBehavior(
050                    mockComponentAdapterSupportingLifecycleStrategy(false, false, true));
051            PicoContainer pico = new DefaultPicoContainer();
052            adapter.dispose(pico);
053            try {
054                adapter.start(pico);
055                fail("IllegalStateException expected");
056            } catch (Exception e) {
057                assertEquals("Already disposed", e.getMessage());
058            }
059        }
060    
061        public void testComponentCannotBeStartedIfAlreadyStarted() {
062            CachingBehavior adapter = new CachingBehavior(
063                    mockComponentAdapterSupportingLifecycleStrategy(true, false, false));
064            PicoContainer pico = new DefaultPicoContainer();
065            adapter.start(pico);
066            try {
067                adapter.start(pico);
068                fail("IllegalStateException expected");
069            } catch (Exception e) {
070                assertEquals("Already started", e.getMessage());
071            }
072        }
073    
074        public void testComponentCannotBeStoppeddIfDisposed() {
075            CachingBehavior adapter = new CachingBehavior(
076                    mockComponentAdapterSupportingLifecycleStrategy(false, false, true));
077            PicoContainer pico = new DefaultPicoContainer();
078            adapter.dispose(pico);
079            try {
080                adapter.stop(pico);
081                fail("IllegalStateException expected");
082            } catch (Exception e) {
083                assertEquals("Already disposed", e.getMessage());
084            }
085        }
086    
087        public void testComponentCannotBeStoppedIfNotStarted() {
088            CachingBehavior adapter = new CachingBehavior(
089                    mockComponentAdapterSupportingLifecycleStrategy(true, true, false));
090            PicoContainer pico = new DefaultPicoContainer();
091            adapter.start(pico);
092            adapter.stop(pico);
093            try {
094            adapter.stop(pico);
095                fail("IllegalStateException expected");
096            } catch (Exception e) {
097                assertEquals("Not started", e.getMessage());
098            }
099        }
100    
101        public void testComponentCannotBeDisposedIfAlreadyDisposed() {
102            CachingBehavior adapter = new CachingBehavior(
103                    mockComponentAdapterSupportingLifecycleStrategy(true, true, true));
104            PicoContainer pico = new DefaultPicoContainer();
105            adapter.start(pico);
106            adapter.stop(pico);
107            adapter.dispose(pico);
108            try {
109                adapter.dispose(pico);
110                fail("IllegalStateException expected");
111            } catch (Exception e) {
112                assertEquals("Already disposed", e.getMessage());
113            }
114        }
115    
116        public void testComponentIsStoppedAndDisposedIfStartedWhenFlushed() {
117            CachingBehavior adapter = new CachingBehavior(
118                    mockComponentAdapterSupportingLifecycleStrategy(true, true, true));
119            PicoContainer pico = new DefaultPicoContainer();
120            adapter.start(pico);
121            adapter.flush();
122        }
123    
124        public void testComponentIsNotStoppedAndDisposedWhenFlushedIfNotStarted() {
125            CachingBehavior adapter = new CachingBehavior(
126                    mockComponentAdapterSupportingLifecycleStrategy(false, false, false));
127            adapter.flush();
128        }
129    
130        public void testComponentIsNotStoppedAndDisposedWhenFlushedIfDelegateDoesNotSupportLifecycle() {
131            CachingBehavior adapter = new CachingBehavior(
132                    mockComponentAdapterNotSupportingLifecycleStrategy());
133            adapter.flush();
134        }
135    
136        public void testLifecycleIsIgnoredIfDelegateDoesNotSupportIt() {
137            CachingBehavior adapter = new CachingBehavior(
138                    mockComponentAdapterNotSupportingLifecycleStrategy());
139            PicoContainer pico = new DefaultPicoContainer();
140            adapter.start(pico);
141            adapter.stop(pico);
142            adapter.dispose(pico);
143        }
144    
145        public void testCanStopAComponentThatWasNeverStartedBecauseItHasNoLifecycle() {
146            MutablePicoContainer pico = new DefaultPicoContainer();
147    
148            pico.addComponent(StringBuffer.class);
149    
150            pico.start();
151    
152            assertNotNull(pico.getComponent(StringBuffer.class));
153    
154            pico.stop();
155            pico.dispose();
156        }
157    
158        private ComponentAdapter mockComponentAdapterNotSupportingLifecycleStrategy() {
159            Mock mock = mock(ComponentAdapter.class);
160            return (ComponentAdapter)mock.proxy();
161        }
162    
163        private ComponentAdapter mockComponentAdapterSupportingLifecycleStrategy(
164                boolean start, boolean stop, boolean dispose) {
165            boolean hasLifecycle = start || stop || dispose;
166            Mock mock = mock(ComponentAdapterSupportingLifecycleStrategy.class);
167            if (start) {
168                mock.expects(atLeastOnce()).method("start").with(isA(Touchable.class));
169            }
170            if (stop) {
171                mock.expects(once()).method("stop").with(isA(Touchable.class));
172            }
173            if (dispose) {
174                mock.expects(once()).method("dispose").with(isA(Touchable.class));
175            }
176            if (hasLifecycle) {
177                mock.stubs().method("getComponentInstance").with(isA(PicoContainer.class)).will(
178                        returnValue(new SimpleTouchable()));
179            }
180            mock.expects(once()).method("getComponentImplementation").will(
181                    returnValue(SimpleTouchable.class));
182            mock.expects(once()).method("hasLifecycle").with(same(SimpleTouchable.class)).will(
183                    returnValue(hasLifecycle));
184            return (ComponentAdapter)mock.proxy();
185        }
186    
187        static interface ComponentAdapterSupportingLifecycleStrategy extends ComponentAdapter,
188                LifecycleStrategy {
189        }
190    }