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