/* * * * 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, "."); } }