blob: c73967f0a26b994fa4830c26d186ceea0673f480 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jackrabbit.commons;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.LinkedList;
import junit.framework.TestCase;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/**
* Simple {@link TestCase} base class for mock-testing the abstract
* JCR implementation classes in this package.
*/
public class MockCase extends TestCase implements MethodInterceptor {
/**
* Mock test state. Set to <code>true</code> when the mock methods
* are being recorded, and to <code>false</code> when the methods are
* being played back.
*/
private boolean recording;
/**
* The recorded mock call sequence. List of {@link MethodCall} objects.
*/
private LinkedList calls;
/**
* The abstract base class being tested.
*/
private Class base;
/**
* Creates a mocked proxy object for the given abstract base class and
* starts recording calls to the object.
*
* @param base the abstract base class being tested
* @return mocked proxy object
*/
protected Object record(Class base) {
this.recording = true;
this.calls = new LinkedList();
this.base = base;
return Enhancer.create(base, base.getInterfaces(), this);
}
/**
* Switches the test state to replaying and verifying the recorded
* call sequence.
*/
protected void replay() {
recording = false;
}
/**
* Verifies that all recorded method calls were executed during
* the verification phase.
*/
protected void verify() {
assertTrue(calls.isEmpty());
}
//---------------------------------------------------< MethodInterceptor >
/**
* Intercepts a method call to the mocked proxy object. Passes the
* call through if the abstract base class being tested implements the
* method, and records or verifies the method call otherwise.
*
* @param object the object on which the method is being called
* @param method the method being called
* @param args method arguments
* @param proxy proxy for re-invoking the called method
* @return method return value
* @throws Throwable if an error occurs
*/
public Object intercept(
Object object, Method method, Object[] args, MethodProxy proxy)
throws Throwable {
try {
base.getDeclaredMethod(method.getName(), method.getParameterTypes());
return proxy.invokeSuper(object, args);
} catch (NoSuchMethodException e) {
if (recording) {
calls.addLast(new MethodCall(method, args));
} else {
assertFalse(calls.isEmpty());
MethodCall call = (MethodCall) calls.removeFirst();
call.assertCall(method, args);
}
return null;
}
}
//----------------------------------------------------------< MethodCall >
/**
* Record of a method call.
*/
private static class MethodCall {
/**
* The method that was called.
*/
private final Method method;
/**
* The arguments that were passed to the method.
*/
private final Object[] args;
/**
* Creates a new method call record.
*
* @param method the method that was called
* @param args the arguments that were passed to the method
*/
public MethodCall(Method method, Object[] args) {
this.method = method;
this.args = args;
}
/**
* Verifies that the given method is the same as was recorded.
*
* @param method the method that was called
* @param args the arguments that were passed to the method
*/
public void assertCall(Method method, Object[] args) {
assertEquals(this.method, method);
assertTrue(Arrays.equals(this.args, args));
}
}
}