/* * * * 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.Field; import java.util.List; import java.util.Set; import static org.unitils.core.util.ObjectFormatter.MOCK_NAME_CHAIN_SEPARATOR; import static org.unitils.util.ReflectionUtils.getAllFields; import static org.unitils.util.ReflectionUtils.getFieldValue; /** * A view that will return a list of suggested assert statements that one can use in a test for the given scenario. * * @author Kenny Claes * @author Filip Neven * @author Tim Ducheyne */ public class SuggestedAssertsReport { /** * Creates a string representation of the given invocations. * * @param testObject The test instance, not null * @param observedInvocations The invocations, not null * @return The string representation, not null */ public String createReport(Object testObject, List<ObservedInvocation> observedInvocations) { StringBuilder result = new StringBuilder(); for (ObservedInvocation mockInvocation : observedInvocations) { // do not output mocked methods (methods that return values) if (Void.TYPE.equals(mockInvocation.getMethod().getReturnType())) { result.append(getSuggestedAssertStatement(testObject, mockInvocation)); result.append("\n"); } } return result.toString(); } /** * Creates an assert statement for the given method invocation and arguments. * * @param testObject The test instance, null if there is no test object * @param observedInvocation The invocation, not null * @return The string representation of the assert statement, not null */ protected String getSuggestedAssertStatement(Object testObject, ObservedInvocation observedInvocation) { StringBuilder result = new StringBuilder(); result.append(formatMockName(observedInvocation)); result.append(".assertInvoked()."); result.append(observedInvocation.getMethod().getName()); result.append("("); boolean firstArgument = true; for (Object argument : observedInvocation.getArguments()) { String testObjectFieldName = getFieldName(testObject, argument); if (!firstArgument) { result.append(", "); } else { firstArgument = false; } if (testObjectFieldName != null) { result.append(testObjectFieldName); } else { result.append(getSuggestedArgument(argument)); } } result.append(");"); return result.toString(); } /** * Creates an appropriate value so that the assert statement will be able to match the given argument value * that was observed in the scenario. * * @param argument The actual argument value, not null * @return The string representation of the value to use in the assert statement, not null */ protected String getSuggestedArgument(Object argument) { if (argument == null) { return "null"; } if (argument instanceof String) { return "\"" + argument + "\""; } if (argument instanceof Number) { return argument.toString(); } if (argument instanceof Character) { return "'" + argument + "'"; } // use null for object values, this will ignore the actual value return "null"; } /** * Checks whether the given argument value is a value of a field in the test object and, if so, returns the * name of that field. * * @param testObject The test instance, null if there is no test object * @param value The value to look for, not null * @return The field name, null if no field was found for the value */ protected String getFieldName(Object testObject, Object value) { if (testObject == null) { return null; } Set<Field> fields = getAllFields(testObject.getClass()); for (Field field : fields) { Object fieldValue = getFieldValue(testObject, field); if (value == fieldValue) { return field.getName(); } } return null; } protected String formatMockName(ObservedInvocation observedInvocation) { String mockName = observedInvocation.getMockName(); return mockName.replaceAll(MOCK_NAME_CHAIN_SEPARATOR, "."); } }