/*
*
* * 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.report.impl;
import org.unitils.mock.core.ObservedInvocation;
import java.lang.reflect.Method;
import java.util.*;
import static org.unitils.core.util.ObjectFormatter.MOCK_NAME_CHAIN_SEPARATOR;
/**
* A view that displays the observed invocations and the location where they were invoked.
* The arguments are shown inline when the length is small enough, else the argument is named using the
* type (eg Person => person1).
* <p/>
* Example: <pre><code>
* 1. mock.method1()) -> string1 ..... at MyTest.testMethod(MyTest.java:60)
* 2. mock.method1("bla", 4) -> null ..... at MyTest.testMethod(MyTest.java:62)
* 3. mock.anotherMethod(myClass1) ..... at MyTest.testMethod(MyTest.java:64)
* <code></pre>
*
* @author Kenny Claes
* @author Filip Neven
* @author Tim Ducheyne
*/
public class ObservedInvocationsReport extends ProxyInvocationsReport {
public ObservedInvocationsReport(Object testedObject) {
super(testedObject);
}
/**
* Creates a string representation of the given invocations as described in the class javadoc.
*
* @param observedInvocations The invocations for which to create a report, not null
* @return The string representation, not null
*/
public String createReport(List<ObservedInvocation> observedInvocations) {
StringBuilder result = new StringBuilder();
List<FormattedObject> currentLargeObjects = new ArrayList<FormattedObject>();
Map<Object, FormattedObject> allLargeObjects = new IdentityHashMap<Object, FormattedObject>();
Map<Class<?>, Integer> largeObjectNameIndexes = new HashMap<Class<?>, Integer>();
// append all invocations
int invocationIndex = 0;
for (ObservedInvocation observedInvocation : observedInvocations) {
result.append(formatInvocationIndex(++invocationIndex, observedInvocations.size()));
result.append(formatObservedInvocation(observedInvocation, currentLargeObjects, allLargeObjects, largeObjectNameIndexes));
result.append(formatInvokedAt(observedInvocation));
result.append("\n");
}
return result.toString();
}
/**
* Creates a string representation of the given invocation.
* If arguments and result values are small enough, they are displayed inline, else the value is replaced by
* a name generated by the {@link #createLargeValueName} method.
*
* @param observedInvocation The invocation to format, not null
* @param currentLargeObjects The current the large values, not null
* @param allLargeObjects All large values per value, not null
* @param largeObjectNameIndexes The current indexes to use for the large value names (per value type), not null
* @return The string representation, not null
*/
protected String formatObservedInvocation(ObservedInvocation observedInvocation, List<FormattedObject> currentLargeObjects, Map<Object, FormattedObject> allLargeObjects, Map<Class<?>, Integer> largeObjectNameIndexes) {
StringBuilder result = new StringBuilder();
Method method = observedInvocation.getMethod();
// append the mock and method name
result.append(formatMockName(observedInvocation));
result.append('.');
result.append(method.getName());
// append the arguments
result.append('(');
Class<?>[] argumentTypes = method.getParameterTypes();
if (argumentTypes.length > 0) {
Iterator<Object> arguments = observedInvocation.getArguments().iterator();
Iterator<Object> argumentsAtInvocationTime = observedInvocation.getArgumentsAtInvocationTime().iterator();
for (Class<?> argumentType : argumentTypes) {
result.append(formatValue(argumentsAtInvocationTime.next(), arguments.next(), argumentType, currentLargeObjects, allLargeObjects, largeObjectNameIndexes));
result.append(", ");
}
// remove the last comma
result.setLength(result.length() - 2);
}
result.append(")");
// append the result value, if the method is non-void
Class<?> resultType = method.getReturnType();
if (!Void.TYPE.equals(resultType)) {
result.append(" -> ");
Object resultValue = observedInvocation.getResult();
Object resultAtInvocationTime = observedInvocation.getResultAtInvocationTime();
result.append(formatValue(resultAtInvocationTime, resultValue, resultType, currentLargeObjects, allLargeObjects, largeObjectNameIndexes));
}
return result.toString();
}
protected String formatMockName(ObservedInvocation observedInvocation) {
String mockName = observedInvocation.getMockName();
return mockName.replaceAll(MOCK_NAME_CHAIN_SEPARATOR, ".");
}
}