Last days I have created a small utility class that would allow me to work with JMock without depending on JUnit. If you develop tests using TestNG and you need mocks a la JMock, than here it is (I have removed the imports so that the listing doesn't go too long):
/**
* An utility class to allow static usage of JMock (removes the restriction
* to subclass JMock specific classes).
*
* @author Alexandru Popescu
*/
public class JMock {
static final Constraint ANYTHING = new IsAnything();
private static final WeakHashMap<Thread, List<Verifiable>> s_mockObjects =
new WeakHashMap<Thread, List<Verifiable>>();
/**
* Creates a mock object that mocks the given type.
* The mock object is named after the type; the exact
* name is calculated by {@link #defaultMockNameForType}.
*
* @param mockedType The type to be mocked.
* @return A {@link Mock} object that mocks <var>mockedType</var>.
*/
public static Mock mock(Class mockedType) {
return mock(mockedType, defaultMockNameForType(mockedType));
}
/**
* Creates a mock object that mocks the given type and is explicitly given a name.
* The mock object is named after the type;
* the exact name is calculated by {@link #defaultMockNameForType}.
*
* @param mockedType The type to be mocked.
* @param roleName The name of the mock object
* @return A {@link Mock} object that mocks <var>mockedType</var>.
*/
public static Mock mock( Class mockedType, String roleName ) {
Mock newMock = new Mock(newCoreMock(mockedType, roleName));
registerToVerify(newMock);
return newMock;
}
public static Mock mock(Class mockedClass,
String roleName,
Class[] constructorArgumentTypes,
Object[] constructorArguments) {
Mock newMock = new Mock(newClassCoreMock(mockedClass,
roleName,
constructorArgumentTypes,
constructorArguments));
registerToVerify(newMock);
return newMock;
}
public static Mock mock(Class mockedClass,
Class[] constructorArgumentTypes,
Object[] constructorArguments) {
return mock(mockedClass,
defaultMockNameForType(mockedClass),
constructorArgumentTypes,
constructorArguments);
}
public static Stub returnValue(Object o) {
return new ReturnStub(o);
}
public static Stub returnValue(boolean result ) {
return returnValue(new Boolean(result));
}
public static Stub returnValue(byte result ) {
return returnValue(new Byte(result));
}
public static Stub returnValue(char result ) {
return returnValue(new Character(result));
}
public static Stub returnValue(short result ) {
return returnValue(new Short(result));
}
public static Stub returnValue(int result ) {
return returnValue(new Integer(result));
}
public static Stub returnValue(long result ) {
return returnValue(new Long(result));
}
public static Stub returnValue(float result ) {
return returnValue(new Float(result));
}
public static Stub returnValue(double result ) {
return returnValue(new Double(result));
}
public static Stub returnIterator(Collection collection) {
return new ReturnIteratorStub(collection);
}
public static Stub returnIterator(Object[] array) {
return new ReturnIteratorStub(array);
}
public static Stub throwException(Throwable throwable) {
return new ThrowStub(throwable);
}
public static InvocationMatcher once() {
return new InvokeOnceMatcher();
}
public static InvocationMatcher atLeastOnce() {
return new InvokeAtLeastOnceMatcher();
}
public static InvocationMatcher exactly(int expectedCount) {
return new InvokeCountMatcher(expectedCount);
}
public static InvocationMatcher never() {
return new TestFailureMatcher("not expected");
}
public static InvocationMatcher never( String errorMessage ) {
return new TestFailureMatcher("not expected ("+errorMessage+")");
}
public static Stub onConsecutiveCalls(Stub... stubs) {
return new StubSequence(stubs);
}
public static Stub doAll(Stub... stubs) {
return new DoAllStub(stubs);
}
public static IsEqual eq(Object operand) {
return new IsEqual(operand);
}
public static IsEqual eq(boolean operand ) {
return eq(new Boolean(operand));
}
public static IsEqual eq(byte operand ) {
return eq(new Byte(operand));
}
public static IsEqual eq(short operand ) {
return eq(new Short(operand));
}
public static IsEqual eq(char operand ) {
return eq(new Character(operand));
}
public static IsEqual eq(int operand ) {
return eq(new Integer(operand));
}
public static IsEqual eq(long operand ) {
return eq(new Long(operand));
}
public static IsEqual eq(float operand ) {
return eq(new Float(operand));
}
public static IsEqual eq(double operand ) {
return eq(new Double(operand));
}
public static IsCloseTo eq( double operand, double error ) {
return new IsCloseTo(operand, error);
}
public static IsSame same( Object operand ) {
return new IsSame(operand);
}
public static IsInstanceOf isA( Class operandClass ) {
return new IsInstanceOf(operandClass);
}
public static StringContains stringContains(String substring) {
return new StringContains(substring);
}
public static StringContains contains(String substring) {
return stringContains(substring);
}
public static StringStartsWith startsWith(String substring ) {
return new StringStartsWith(substring);
}
public static StringEndsWith endsWith(String substring ) {
return new StringEndsWith(substring);
}
public static IsNot not(Constraint c ) {
return new IsNot(c);
}
public static And and(Constraint left, Constraint right ) {
return new And(left, right);
}
public static Or or(Constraint left, Constraint right ) {
return new Or(left, right);
}
/// HINT: not sure about these following 3
public static Object newDummy( Class dummyType ) {
return Dummy.newDummy(dummyType);
}
/// HINT: what is this?
public static Object newDummy( Class dummyType, String name ) {
return Dummy.newDummy(dummyType, name);
}
/// HINT: what is this?
public static Object newDummy( String name ) {
return Dummy.newDummy(name);
}
public static void assertThat(Object actual, Constraint constraint) {
if (!constraint.eval(actual)) {
StringBuffer message = new StringBuffer("\nExpected: ");
constraint.describeTo(message);
message.append("\n got : ").append(actual).append('\n');
throw new AssertionError(message);
}
}
public static void assertThat(boolean actual, Constraint constraint) {
assertThat(new Boolean(actual), constraint);
}
public static void assertThat(byte actual, Constraint constraint) {
assertThat(new Byte(actual), constraint);
}
public static void assertThat(short actual, Constraint constraint) {
assertThat(new Short(actual), constraint);
}
public static void assertThat(char actual, Constraint constraint) {
assertThat(new Character(actual), constraint);
}
public static void assertThat(int actual, Constraint constraint) {
assertThat(new Integer(actual), constraint);
}
public static void assertThat(long actual, Constraint constraint) {
assertThat(new Long(actual), constraint);
}
public static void assertThat(float actual, Constraint constraint) {
assertThat(new Float(actual), constraint);
}
public static void assertThat(double actual, Constraint constraint) {
assertThat(new Double(actual), constraint);
}
public static HasPropertyWithValue hasProperty(String propertyName, Constraint expectation) {
return new HasPropertyWithValue(propertyName, expectation);
}
public static HasProperty hasProperty(String propertyName) {
return new HasProperty(propertyName);
}
public static HasToString toString(Constraint toStringConstraint) {
return new HasToString(toStringConstraint);
}
public static IsCompatibleType compatibleType(Class baseType) {
return new IsCompatibleType(baseType);
}
public static IsIn isIn(Collection collection) {
return new IsIn(collection);
}
public static IsIn isIn(Object[] array) {
return new IsIn(array);
}
public static IsCollectionContaining collectionContaining(Constraint elementConstraint) {
return new IsCollectionContaining(elementConstraint);
}
public static IsCollectionContaining collectionContaining(Object element) {
return collectionContaining(eq(element));
}
public static IsArrayContaining arrayContaining(Constraint elementConstraint) {
return new IsArrayContaining(elementConstraint);
}
public static IsArrayContaining arrayContaining(Object element) {
return arrayContaining(eq(element));
}
public static IsArrayContaining arrayContaining(boolean element) {
return arrayContaining(new Boolean(element));
}
public static IsArrayContaining arrayContaining(byte element) {
return arrayContaining(new Byte(element));
}
public static IsArrayContaining arrayContaining(short element) {
return arrayContaining(new Short(element));
}
public static IsArrayContaining arrayContaining(char element) {
return arrayContaining(new Character(element));
}
public static IsArrayContaining arrayContaining(int element) {
return arrayContaining(new Integer(element));
}
public static IsArrayContaining arrayContaining(long element) {
return arrayContaining(new Long(element));
}
public static IsArrayContaining arrayContaining(float element) {
return arrayContaining(new Float(element));
}
public static IsArrayContaining arrayContaining(double element) {
return arrayContaining(new Double(element));
}
public static IsMapContaining mapContaining(Constraint keyConstraint, Constraint valueConstraint) {
return new IsMapContaining(keyConstraint, valueConstraint);
}
public static IsMapContaining mapContaining(Object key, Object value) {
return mapContaining(eq(key), eq(value));
}
public static IsMapContaining mapWithKey(Object key) {
return mapWithKey(eq(key));
}
public static IsMapContaining mapWithKey(Constraint keyConstraint) {
return new IsMapContaining(keyConstraint, ANYTHING);
}
public static IsMapContaining mapWithValue(Object value) {
return mapWithValue(eq(value));
}
public static IsMapContaining mapWithValue(Constraint valueConstraint) {
return new IsMapContaining(ANYTHING, valueConstraint);
}
/**
* Verify the expected behavior for the mock registered by the current thread.
*/
public static void verify() {
List<Verifiable> mocks = s_mockObjects.get(Thread.currentThread());
if(null != mocks) {
for(Verifiable verifiable : mocks) {
verifiable.verify();
}
}
}
/**
* Verify the expected behavior for the mocks defined as fields of the arguement object.
*
* @param object the object to be inspected
*/
public static void verifyObject(Object object) {
Verifier.verifyObject(object);
}
/**
* Helper method that delegates to {@link #verify()} and {@link verifyObject(Object)}.
*/
public static void verifyAll(Object object) {
verify();
verifyObject(object);
}
/**
* Verify the expected behavior for the mocks registered by the current thread and
* also releases them.
*/
public static synchronized void verifyAndRelease() {
Thread currentThread= Thread.currentThread();
List<Verifiable> mocks = s_mockObjects.get(currentThread);
if(null != mocks) {
for(Verifiable verifiable : mocks) {
verifiable.verify();
}
}
mocks.clear();
s_mockObjects.put(currentThread, null);
}
/**
* Helper method delegating to {@link #verifyAndRelease()} and {@link #verifyObject(Object)}.
*/
public static void verifyAllAndRelese(Object object) {
verifyAndRelease();
verifyObject(object);
}
///
private static synchronized void registerToVerify(Verifiable verifiable) {
List<Verifiable> mocks = s_mockObjects.get(Thread.currentThread());
if(null == mocks) {
mocks = new ArrayList<Verifiable>();
s_mockObjects.put(Thread.currentThread(), mocks);
}
mocks.add(verifiable);
}
private static DynamicMock newCoreMock(Class mockedType, String roleName ) {
return new CoreMock(mockedType, roleName);
}
private static DynamicMock newClassCoreMock(Class mockedClass,
String roleName,
Class[] constructorArgumentTypes,
Object[] constructorArguments) {
return new CGLIBCoreMock(mockedClass, roleName, constructorArgumentTypes, constructorArguments);
}
/**
* Calculates a default role name for a mocked type.
* @param mockedType
* @return
*/
private static String defaultMockNameForType(Class mockedType) {
return "mock" + Formatting.classShortName(mockedType);
}
}
It works for mocking both interfaces and classes (through CGLIB). And here is a short example of usage (JDK5, because I use static imports):
public class TypeAccessFilterTest {
@Test
public void jmockBotNormalRequest() throws IOException, ServletException {
// static imports
Mock mockBotChecker = mock(BotChecker.class, new Class[0], new Object[0]);
Mock mockFilterChain= mock(FilterChain.class);
TypeAccessFilter taf= new TypeAccessFilter();
taf.setBotChecker((BotChecker) mockBotChecker.proxy());
mockFilterChain.expects(once()).method("doFilter")
.with(isA(HttpServletRequest.class),
isA(JSessionidBeautifierHttpResponseWrapper.class));
taf.doFilter(m_mockRequest, m_mockResponse, (FilterChain) mockFilterChain.proxy());
verifyAndRelease();
}
As far as I know the latest versions of EasyMock allow the same JUnit-free usage, which in my opinion is a great thing.





