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.lifecycle; 009 010 import static org.junit.Assert.assertFalse; 011 import static org.picocontainer.tck.MockFactory.mockeryWithCountingNamingScheme; 012 013 import java.io.Serializable; 014 import java.lang.reflect.Member; 015 import java.lang.reflect.Method; 016 017 import org.hamcrest.BaseMatcher; 018 import org.hamcrest.Description; 019 import org.hamcrest.Matcher; 020 import org.jmock.Expectations; 021 import org.jmock.Mockery; 022 import org.jmock.integration.junit4.JMock; 023 import org.junit.Before; 024 import org.junit.Test; 025 import org.junit.runner.RunWith; 026 import org.picocontainer.ComponentAdapter; 027 import org.picocontainer.ComponentMonitor; 028 import org.picocontainer.Disposable; 029 import org.picocontainer.PicoContainer; 030 import org.picocontainer.Startable; 031 032 /** 033 * @author Paul Hammant 034 * @author Mauro Talevi 035 * @author Jörg Schaible 036 */ 037 @RunWith(JMock.class) 038 public class ReflectionLifecycleStrategyTestCase { 039 040 private Mockery mockery = mockeryWithCountingNamingScheme(); 041 042 private ReflectionLifecycleStrategy strategy; 043 private ComponentMonitor componentMonitor; 044 045 @Before 046 public void setUp() { 047 componentMonitor = mockery.mock(ComponentMonitor.class); 048 strategy = new ReflectionLifecycleStrategy(componentMonitor); 049 } 050 051 @Test 052 public void testStartable() { 053 Object startable = mockComponent(true, false); 054 strategy.start(startable); 055 strategy.stop(startable); 056 strategy.dispose(startable); 057 } 058 059 @Test 060 public void testDisposable() { 061 Object disposable = mockComponent(false, true); 062 strategy.start(disposable); 063 strategy.stop(disposable); 064 strategy.dispose(disposable); 065 } 066 067 @Test 068 public void testNotStartableNorDisposable() { 069 Object serializable = mockery.mock(Serializable.class); 070 assertFalse(strategy.hasLifecycle(serializable.getClass())); 071 strategy.start(serializable); 072 strategy.stop(serializable); 073 strategy.dispose(serializable); 074 } 075 076 @Test 077 public void testMonitorChanges() { 078 final ComponentMonitor componentMonitor2 = mockery 079 .mock(ComponentMonitor.class); 080 final Disposable disposable = mockery.mock(Disposable.class); 081 final Matcher<Member> isDisposeMember = new IsMember("dispose"); 082 final Matcher<Method> isDisposeMethod = new IsMethod("dispose"); 083 mockery.checking(new Expectations() { 084 { 085 atLeast(1).of(disposable).dispose(); 086 one(componentMonitor).invoking( 087 with(aNull(PicoContainer.class)), 088 with(aNull(ComponentAdapter.class)), 089 with(isDisposeMember), with(same(disposable))); 090 one(componentMonitor).invoked(with(aNull(PicoContainer.class)), 091 with(aNull(ComponentAdapter.class)), 092 with(isDisposeMethod), with(same(disposable)), 093 with(any(Long.class))); 094 one(componentMonitor2).invoking( 095 with(aNull(PicoContainer.class)), 096 with(aNull(ComponentAdapter.class)), 097 with(isDisposeMember), with(same(disposable))); 098 one(componentMonitor2).invoked( 099 with(aNull(PicoContainer.class)), 100 with(aNull(ComponentAdapter.class)), 101 with(isDisposeMethod), with(same(disposable)), 102 with(any(Long.class))); 103 } 104 }); 105 strategy.dispose(disposable); 106 strategy.changeMonitor(componentMonitor2); 107 strategy.dispose(disposable); 108 } 109 110 @Test 111 public void testWithDifferentTypes() { 112 final MyLifecycle lifecycle = mockery.mock(MyLifecycle.class); 113 final Matcher<Member> isStartMember = new IsMember("start"); 114 final Matcher<Method> isStartMethod = new IsMethod("start"); 115 final Matcher<Member> isStopMember = new IsMember("stop"); 116 final Matcher<Method> isStopMethod = new IsMethod("stop"); 117 final Matcher<Member> isDisposeMember = new IsMember("dispose"); 118 final Matcher<Method> isDisposeMethod = new IsMethod("dispose"); 119 mockery.checking(new Expectations() { 120 { 121 one(lifecycle).start(); 122 one(lifecycle).stop(); 123 one(lifecycle).dispose(); 124 one(componentMonitor).invoking( 125 with(aNull(PicoContainer.class)), 126 with(aNull(ComponentAdapter.class)), 127 with(isStartMember), with(same(lifecycle))); 128 one(componentMonitor).invoked(with(aNull(PicoContainer.class)), 129 with(aNull(ComponentAdapter.class)), 130 with(isStartMethod), with(same(lifecycle)), 131 with(any(Long.class))); 132 one(componentMonitor).invoking( 133 with(aNull(PicoContainer.class)), 134 with(aNull(ComponentAdapter.class)), 135 with(isStopMember), with(same(lifecycle))); 136 one(componentMonitor).invoked(with(aNull(PicoContainer.class)), 137 with(aNull(ComponentAdapter.class)), 138 with(isStopMethod), with(same(lifecycle)), 139 with(any(Long.class))); 140 one(componentMonitor).invoking( 141 with(aNull(PicoContainer.class)), 142 with(aNull(ComponentAdapter.class)), 143 with(isDisposeMember), with(same(lifecycle))); 144 one(componentMonitor).invoked(with(aNull(PicoContainer.class)), 145 with(aNull(ComponentAdapter.class)), 146 with(isDisposeMethod), with(same(lifecycle)), 147 with(any(Long.class))); 148 } 149 }); 150 151 Object startable = mockComponent(true, false); 152 strategy.start(startable); 153 strategy.stop(startable); 154 strategy.dispose(startable); 155 startable = lifecycle; 156 strategy.start(startable); 157 strategy.stop(startable); 158 strategy.dispose(startable); 159 } 160 161 private Object mockComponent(boolean startable, boolean disposable) { 162 final Matcher<Member> isStartMember = new IsMember("start"); 163 final Matcher<Method> isStartMethod = new IsMethod("start"); 164 final Matcher<Member> isStopMember = new IsMember("stop"); 165 final Matcher<Method> isStopMethod = new IsMethod("stop"); 166 final Matcher<Member> isDisposeMember = new IsMember("dispose"); 167 final Matcher<Method> isDisposeMethod = new IsMethod("dispose"); 168 if (startable) { 169 final Startable mock = mockery.mock(Startable.class); 170 mockery.checking(new Expectations() { 171 { 172 atLeast(1).of(mock).start(); 173 atLeast(1).of(mock).stop(); 174 one(componentMonitor).invoking( 175 with(aNull(PicoContainer.class)), 176 with(aNull(ComponentAdapter.class)), 177 with(isStartMember), with(same(mock))); 178 one(componentMonitor) 179 .invoked(with(aNull(PicoContainer.class)), 180 with(aNull(ComponentAdapter.class)), 181 with(isStartMethod), with(same(mock)), 182 with(any(Long.class))); 183 one(componentMonitor).invoking( 184 with(aNull(PicoContainer.class)), 185 with(aNull(ComponentAdapter.class)), 186 with(isStopMember), with(same(mock))); 187 one(componentMonitor).invoked( 188 with(aNull(PicoContainer.class)), 189 with(aNull(ComponentAdapter.class)), 190 with(isStopMethod), with(same(mock)), with(any(Long.class))); 191 } 192 }); 193 return mock; 194 } 195 if (disposable) { 196 final Disposable mock = mockery.mock(Disposable.class); 197 mockery.checking(new Expectations() { 198 { 199 atLeast(1).of(mock).dispose(); 200 one(componentMonitor).invoking( 201 with(aNull(PicoContainer.class)), 202 with(aNull(ComponentAdapter.class)), 203 with(isDisposeMember), with(same(mock))); 204 one(componentMonitor) 205 .invoked(with(aNull(PicoContainer.class)), 206 with(aNull(ComponentAdapter.class)), 207 with(isDisposeMethod), with(same(mock)), 208 with(any(Long.class))); 209 } 210 }); 211 return mock; 212 } 213 return mockery.mock(Serializable.class); 214 } 215 216 public static interface MyLifecycle { 217 void start(); 218 219 void stop(); 220 221 void dispose(); 222 } 223 224 static class IsMember extends BaseMatcher<Member> { 225 private String name; 226 227 public IsMember(String name) { 228 this.name = name; 229 } 230 231 public boolean matches(Object item) { 232 return ((Member) item).getName().equals(name); 233 } 234 235 public void describeTo(Description description) { 236 description.appendText("Should have been a member of name "); 237 description.appendText(name); 238 } 239 }; 240 241 static class IsMethod extends BaseMatcher<Method> { 242 private String name; 243 244 public IsMethod(String name) { 245 this.name = name; 246 } 247 248 public boolean matches(Object item) { 249 return ((Method) item).getName().equals(name); 250 } 251 252 public void describeTo(Description description) { 253 description.appendText("Should have been a method of name "); 254 description.appendText(name); 255 } 256 }; 257 258 }