/*
*
* * Copyright 2010, Unitils.org
* *
* * Licensed 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.unitils.mock.mockbehavior.impl;
import org.unitils.mock.core.proxy.ProxyInvocation;
import org.unitils.mock.dummy.DummyObjectUtil;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* Mock behavior that returns a default value. The default value for an object will be a proxy object with the same behaviour. When doing
* the same call multiple times the same 'proxy' object will be returned each time. Doing the same method call with other parameters will
* howerver result a new object returned.
* <p/>
* Following defaults are used:
* <ul>
* <li>Number values: 0</li>
* <li>Object values: DummyObject</li>
* <li>Collection: DummyObject</li>
* <li>arrays etc: empty values</li>
* </ul>
* <p/>
*
* @author Jeroen Horemans
*/
public class DummyValueReturningMockBehavior extends DefaultValueReturningMockBehavior {
/*
* this list keeps track of what object we have returned. So that we return the "same" instance on each invocation
*/
private Map<MethodKey, Object> returnValues = new HashMap<MethodKey, Object>();
/**
* Executes the mock behavior.
*
* @param proxyInvocation The proxy method invocation, not null
* @return The default value defined by this behavior
*/
public Object execute(ProxyInvocation proxyInvocation) {
Object result = null;
Method method = proxyInvocation.getMethod();
Class<?> returnType = method.getReturnType();
MethodKey key = new MethodKey(method.getName(), proxyInvocation.getArguments());
if (returnValues.containsKey(key)) {
result = returnValues.get(key);
}
if (result == null) {
result = super.execute(proxyInvocation);
}
if (result == null && String.class.equals(returnType)) {
result = "";
}
if (result == null && isDummyProof(returnType)) {
result = DummyObjectUtil.createDummy(returnType, new DummyValueReturningMockBehavior());
}
returnValues.put(key, result);
return result;
}
private boolean isDummyProof(Class<?> returnType) {
return !returnType.isPrimitive() && !(returnType == Void.TYPE) && !Modifier.isFinal(returnType.getModifiers());
}
private class MethodKey {
private String methodName;
private List<Object> arguments;
public MethodKey(String methodName, List<Object> arguments) {
this.methodName = methodName;
this.arguments = arguments;
}
@Override
public int hashCode() {
return methodName.hashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
MethodKey other = (MethodKey) obj;
if (methodName == null) {
if (other.methodName != null) {
return false;
}
} else if (!methodName.equals(other.methodName)) {
return false;
}
if (arguments.size() != other.arguments.size()) {
return false;
}
if (arguments.size() > 0) {
Iterator<Object> it2 = other.arguments.iterator();
for (Iterator<Object> it1 = arguments.iterator(); it1.hasNext();) {
Object object1 = it1.next();
Object object2 = it2.next();
if (object1 == null && object2 == null) {
continue;
} else if (object1 != null && !object1.equals(object2)) {
return false;
}
}
}
return true;
}
}
}