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)); 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)); 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)); 062 PicoContainer pico = new DefaultPicoContainer(); 063 adapter.dispose(pico); 064 try { 065 adapter.start(pico); 066 fail("IllegalStateException expected"); 067 } catch (Exception e) { 068 assertEquals("Already disposed", e.getMessage()); 069 } 070 } 071 072 @Test public void testComponentCannotBeStartedIfAlreadyStarted() { 073 Cached adapter = new Cached( 074 mockComponentAdapterSupportingLifecycleStrategy(true, false, false)); 075 PicoContainer pico = new DefaultPicoContainer(); 076 adapter.start(pico); 077 try { 078 adapter.start(pico); 079 fail("IllegalStateException expected"); 080 } catch (Exception e) { 081 assertEquals("Already started", e.getMessage()); 082 } 083 } 084 085 @Test public void testComponentCannotBeStoppeddIfDisposed() { 086 Cached adapter = new Cached( 087 mockComponentAdapterSupportingLifecycleStrategy(false, false, true)); 088 PicoContainer pico = new DefaultPicoContainer(); 089 adapter.dispose(pico); 090 try { 091 adapter.stop(pico); 092 fail("IllegalStateException expected"); 093 } catch (Exception e) { 094 assertEquals("Already disposed", e.getMessage()); 095 } 096 } 097 098 @Test public void testComponentCannotBeStoppedIfNotStarted() { 099 Cached adapter = new Cached( 100 mockComponentAdapterSupportingLifecycleStrategy(true, true, false)); 101 PicoContainer pico = new DefaultPicoContainer(); 102 adapter.start(pico); 103 adapter.stop(pico); 104 try { 105 adapter.stop(pico); 106 fail("IllegalStateException expected"); 107 } catch (Exception e) { 108 assertEquals("Not started", e.getMessage()); 109 } 110 } 111 112 @Test public void testComponentCannotBeDisposedIfAlreadyDisposed() { 113 Cached adapter = new Cached( 114 mockComponentAdapterSupportingLifecycleStrategy(true, true, true)); 115 PicoContainer pico = new DefaultPicoContainer(); 116 adapter.start(pico); 117 adapter.stop(pico); 118 adapter.dispose(pico); 119 try { 120 adapter.dispose(pico); 121 fail("IllegalStateException expected"); 122 } catch (Exception e) { 123 assertEquals("Already disposed", e.getMessage()); 124 } 125 } 126 127 @Test public void testComponentIsStoppedAndDisposedIfStartedWhenFlushed() { 128 Cached adapter = new Cached( 129 mockComponentAdapterSupportingLifecycleStrategy(true, true, true)); 130 PicoContainer pico = new DefaultPicoContainer(); 131 adapter.start(pico); 132 adapter.flush(); 133 } 134 135 @Test public void testComponentIsNotStoppedAndDisposedWhenFlushedIfNotStarted() { 136 Cached adapter = new Cached( 137 mockComponentAdapterSupportingLifecycleStrategy(false, false, false)); 138 adapter.flush(); 139 } 140 141 @Test public void testComponentIsNotStoppedAndDisposedWhenFlushedIfDelegateDoesNotSupportLifecycle() { 142 Cached adapter = new Cached( 143 mockComponentAdapterNotSupportingLifecycleStrategy()); 144 adapter.flush(); 145 } 146 147 @Test public void testLifecycleIsIgnoredIfDelegateDoesNotSupportIt() { 148 Cached adapter = new Cached( 149 mockComponentAdapterNotSupportingLifecycleStrategy()); 150 PicoContainer pico = new DefaultPicoContainer(); 151 adapter.start(pico); 152 adapter.stop(pico); 153 adapter.dispose(pico); 154 } 155 156 @Test public void testCanStopAComponentThatWasNeverStartedBecauseItHasNoLifecycle() { 157 MutablePicoContainer pico = new DefaultPicoContainer(); 158 159 pico.addComponent(StringBuffer.class); 160 161 pico.start(); 162 163 assertNotNull(pico.getComponent(StringBuffer.class)); 164 165 pico.stop(); 166 pico.dispose(); 167 } 168 169 private ComponentAdapter mockComponentAdapterNotSupportingLifecycleStrategy() { 170 return mockery.mock(ComponentAdapter.class); 171 } 172 173 private ComponentAdapter mockComponentAdapterSupportingLifecycleStrategy( 174 final boolean start, final boolean stop, final boolean dispose) { 175 final boolean hasLifecycle = start || stop || dispose; 176 final ComponentAdapterSupportingLifecycleStrategy ca = mockery.mock(ComponentAdapterSupportingLifecycleStrategy.class); 177 mockery.checking(new Expectations(){{ 178 if (start) { 179 atLeast(1).of(ca).start(with(any(Touchable.class))); 180 } 181 if (stop) { 182 one(ca).stop(with(any(Touchable.class))); 183 } 184 if (dispose) { 185 one(ca).dispose(with(any(Touchable.class))); 186 } 187 if (hasLifecycle) { 188 one(ca).getComponentInstance(with(any(PicoContainer.class)), with(same(ComponentAdapter.NOTHING.class))); 189 will(returnValue(new SimpleTouchable())); 190 } 191 one(ca).getComponentImplementation(); 192 will(returnValue(SimpleTouchable.class)); 193 one(ca).hasLifecycle(with(same(SimpleTouchable.class))); 194 will(returnValue(hasLifecycle)); 195 }}); 196 return ca; 197 } 198 199 public static interface ComponentAdapterSupportingLifecycleStrategy extends ComponentAdapter, 200 LifecycleStrategy { 201 } 202 }