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)), with(any(Object[].class)));
090 one(componentMonitor).invoked(with(aNull(PicoContainer.class)),
091 with(aNull(ComponentAdapter.class)),
092 with(isDisposeMethod), with(same(disposable)),
093 with(any(Long.class)), with(any(Object[].class)), with(same(null)));
094 one(componentMonitor2).invoking(
095 with(aNull(PicoContainer.class)),
096 with(aNull(ComponentAdapter.class)),
097 with(isDisposeMember), with(same(disposable)), with(any(Object[].class)));
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)), with(any(Object[].class)), with(same(null)));
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)), with(any(Object[].class)));
128 one(componentMonitor).invoked(with(aNull(PicoContainer.class)),
129 with(aNull(ComponentAdapter.class)),
130 with(isStartMethod), with(same(lifecycle)),
131 with(any(Long.class)), with(any(Object[].class)), with(same(null)));
132 one(componentMonitor).invoking(
133 with(aNull(PicoContainer.class)),
134 with(aNull(ComponentAdapter.class)),
135 with(isStopMember), with(same(lifecycle)), with(any(Object[].class)));
136 one(componentMonitor).invoked(with(aNull(PicoContainer.class)),
137 with(aNull(ComponentAdapter.class)),
138 with(isStopMethod), with(same(lifecycle)),
139 with(any(Long.class)), with(any(Object[].class)), with(same(null)));
140 one(componentMonitor).invoking(
141 with(aNull(PicoContainer.class)),
142 with(aNull(ComponentAdapter.class)),
143 with(isDisposeMember), with(same(lifecycle)), with(any(Object[].class)));
144 one(componentMonitor).invoked(with(aNull(PicoContainer.class)),
145 with(aNull(ComponentAdapter.class)),
146 with(isDisposeMethod), with(same(lifecycle)),
147 with(any(Long.class)), with(any(Object[].class)), with(same(null)));
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)), with(any(Object[].class)));
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)), with(any(Object[].class)), with(same(null)));
183 one(componentMonitor).invoking(
184 with(aNull(PicoContainer.class)),
185 with(aNull(ComponentAdapter.class)),
186 with(isStopMember), with(same(mock)), with(any(Object[].class)));
187 one(componentMonitor).invoked(
188 with(aNull(PicoContainer.class)),
189 with(aNull(ComponentAdapter.class)),
190 with(isStopMethod), with(same(mock)), with(any(Long.class)), with(any(Object[].class)), with(same(null)));
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)), with(any(Object[].class)));
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)), with(any(Object[].class)), with(same(null)));
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 }