001 // Copyright 2006 Howard M. Lewis Ship
002 //
003 // Licensed under the Apache License, Version 2.0 (the "License");
004 // you may not use this file except in compliance with the License.
005 // You may obtain a copy of the License at
006 //
007 // http://www.apache.org/licenses/LICENSE-2.0
008 //
009 // Unless required by applicable law or agreed to in writing, software
010 // distributed under the License is distributed on an "AS IS" BASIS,
011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012 // See the License for the specific language governing permissions and
013 // limitations under the License.
014
015 /**
016 *
017 */
018 package com.javaforge.tapestry.testng;
019
020 import org.easymock.IArgumentMatcher;
021
022 import static org.easymock.EasyMock.reportMatcher;
023
024 /**
025 * An EasyMock 2.0 argument matcher that captures a method argument value. This allows an object
026 * created inside a test method to be interrogated after the method completes, even when the object
027 * is not a return value, but is merely passed as a parameter to a mock object.
028 *
029 * @author Howard M. Lewis Ship
030 * @param <T>
031 * the type of object to capture
032 */
033 public final class Capturer<T> implements IArgumentMatcher
034 {
035 private final Class<T> _matchType;
036
037 private T _captured;
038
039 /**
040 * Creates a new Capturer for the given type. Because of Generics syntax, it is easier to use
041 * the static method.
042 */
043 public Capturer(Class<T> matchType)
044 {
045 _matchType = matchType;
046 }
047
048 /**
049 * Factory method that invokes the normal constructor in a way that keeps Java Generics happy.
050 */
051 public static <T> Capturer<T> newCapturer(Class<T> matchType)
052 {
053 return new Capturer<T>(matchType);
054 }
055
056 public void appendTo(StringBuffer buffer)
057 {
058 buffer.append(String.format("capture(%s)", _matchType.getName()));
059 }
060
061 public boolean matches(Object parameter)
062 {
063 boolean result = _matchType.isInstance(parameter);
064
065 if (result)
066 _captured = _matchType.cast(parameter);
067
068 return result;
069 }
070
071 /** Returns the method argument value previously captured. */
072 public T getCaptured()
073 {
074 return _captured;
075 }
076
077 /**
078 * Useage (with static imports):
079 * <p>
080 * Capturer<Type> c = newCapturer(Type.class);
081 * <p>
082 * mock.someMethod(capture(c));
083 * <p> . . .
084 * <p>
085 * c.getCaptured().getXXX()
086 * <p>
087 * The interrogation of the captured argument should occur after the test subject has invoked
088 * the method on the mock; the best time for this is typically after invoking
089 * {@link TestBase#verify()}.
090 * <p>
091 * Remember that when you use an argument matcher for one argument of a method invocation, you
092 * must use argument matchers for <em>all</em> arguments of the method invocation.
093 */
094 public static <T> T capture(Capturer<T> capturer)
095 {
096 reportMatcher(capturer);
097
098 return null;
099 }
100
101 }