All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.unitils.reflectionassert.ReflectionAssert Maven / Gradle / Ivy

/*
 *
 *  * 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.reflectionassert;


import junit.framework.Assert;
import junit.framework.AssertionFailedError;
import ognl.DefaultMemberAccess;
import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Transformer;
import org.apache.commons.lang.StringUtils;
import org.unitils.core.UnitilsException;
import org.unitils.reflectionassert.difference.Difference;
import org.unitils.reflectionassert.report.impl.DefaultDifferenceReport;
import org.unitils.util.ReflectionUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.Set;

import static junit.framework.Assert.assertNotNull;
import static org.unitils.reflectionassert.ReflectionComparatorFactory.createRefectionComparator;
import static org.unitils.reflectionassert.ReflectionComparatorMode.IGNORE_DEFAULTS;
import static org.unitils.reflectionassert.ReflectionComparatorMode.LENIENT_ORDER;


/**
 * A class for asserting that 2 objects/collections are equal by comparing properties and fields of the
 * objects/collections using reflection.
 * 

* The (combination of) comparator modes specify how strict the comparison must be:

    *
  • ignore defaults: compare only arguments (and inner values) that have a non default value (eg null) as expected value
  • *
  • lenient dates: do not compare actual date values, just that they both have a value or not
  • *
  • lenient order: order is not important when comparing collections or arrays
  • *
*

* There are 2 versions of each method: a lenient and a reflection version. * With the ref versions you can set the comparator modes explicitly (note: no modes means strict comparison). The len * versions are the same as the ref versions but have lenient order and ignore defaults set by default. *

* The name assert..ReflectionEquals is chosen instead of assert..Equals so it can be added as a static import * without naming collisions. * * @author Tim Ducheyne * @author Filip Neven * @see ReflectionComparator * @see ReflectionComparatorMode */ public class ReflectionAssert { /** * Asserts that two objects are equal. Reflection is used to compare all fields of these values. * If they are not equal an AssertionFailedError is thrown. *

* This is identical to assertReflectionEquals with * lenient order and ignore defaults set as comparator modes. * * @param expected the expected object * @param actual the given object * @throws AssertionFailedError when both objects are not equals */ public static void assertLenientEquals(Object expected, Object actual) throws AssertionFailedError { assertLenientEquals(null, expected, actual); } /** * Asserts that two objects are equal. Reflection is used to compare all fields of these values. * If they are not equal an AssertionFailedError is thrown. *

* The comparator modes determine how strict to compare the values. * * @param expected the expected object * @param actual the given object * @param modes the comparator modes * @throws AssertionFailedError when both objects are not equals */ public static void assertReflectionEquals(Object expected, Object actual, ReflectionComparatorMode... modes) throws AssertionFailedError { assertReflectionEquals(null, expected, actual, modes); } /** * Asserts that two objects are equal. Reflection is used to compare all fields of these values. * If they are not equal an AssertionFailedError is thrown. *

* This is identical to assertReflectionEquals with * lenient order and ignore defaults set as comparator modes. * * @param message a message for when the assertion fails * @param expected the expected object * @param actual the given object * @throws AssertionFailedError when both objects are not equals */ public static void assertLenientEquals(String message, Object expected, Object actual) throws AssertionFailedError { assertReflectionEquals(message, expected, actual, LENIENT_ORDER, IGNORE_DEFAULTS); } /** * Asserts that two objects are equal. Reflection is used to compare all fields of these values. * If they are not equal an AssertionFailedError is thrown. *

* The comparator modes determine how strict to compare the values. * * @param message a message for when the assertion fails * @param expected the expected object * @param actual the given object * @param modes the comparator modes * @throws AssertionFailedError when both objects are not equals */ public static void assertReflectionEquals(String message, Object expected, Object actual, ReflectionComparatorMode... modes) throws AssertionFailedError { ReflectionComparator reflectionComparator = createRefectionComparator(modes); Difference difference = reflectionComparator.getDifference(expected, actual); if (difference != null) { Assert.fail(getFailureMessage(message, difference)); } } /** * @param message a custom user-provided message, null if the user didn't provide a message * @param difference the difference, not null * @return a failure message describing the difference found */ protected static String getFailureMessage(String message, Difference difference) { StringBuilder failureMessage = new StringBuilder(); failureMessage.append(message == null ? "" : message + "\n"); failureMessage.append(new DefaultDifferenceReport().createReport(difference)); return failureMessage.toString(); } /** * Asserts that the value of a property of an object is equal to the given value. *

* Bean notation can be used to specify inner properties. Eg myArray[2].innerValue. * assertLenientEquals is used to check whether both values are equal. *

* This is identical to assertPropertyReflectionEquals with * lenient order and ignore defaults set as comparator modes. * * @param propertyName the property, not null * @param expectedPropertyValue the expected value * @param actualObject the object that contains the property * @throws AssertionFailedError when both objects are not equals */ public static void assertPropertyLenientEquals(String propertyName, Object expectedPropertyValue, Object actualObject) throws AssertionFailedError { assertPropertyLenientEquals(null, propertyName, expectedPropertyValue, actualObject); } /** * Asserts that the value of a property of an object is equal to the given value. *

* Bean notation can be used to specify inner properties. Eg myArray[2].innerValue. * assertReflectionEquals is used to check whether both values are equal. *

* The comparator modes determine how strict to compare the values. * * @param propertyName the property, not null * @param expectedPropertyValue the expected value * @param actualObject the object that contains the property * @param modes the comparator modes * @throws AssertionFailedError when both objects are not equals */ public static void assertPropertyReflectionEquals(String propertyName, Object expectedPropertyValue, Object actualObject, ReflectionComparatorMode... modes) throws AssertionFailedError { assertPropertyReflectionEquals(null, propertyName, expectedPropertyValue, actualObject, modes); } /** * Asserts that the value of a property of an object is equal to the given value. *

* Bean notation can be used to specify inner properties. Eg myArray[2].innerValue. * assertReflectionEquals is used to check whether both values are equal. *

* This is identical to assertPropertyReflectionEquals with * lenient order and ignore defaults set as comparator modes. * * @param message a message for when the assertion fails * @param propertyName the property, not null * @param expectedPropertyValue the expected value * @param actualObject the object that contains the property * @throws AssertionFailedError when both objects are not equals */ public static void assertPropertyLenientEquals(String message, String propertyName, Object expectedPropertyValue, Object actualObject) throws AssertionFailedError { assertPropertyReflectionEquals(message, propertyName, expectedPropertyValue, actualObject, LENIENT_ORDER, IGNORE_DEFAULTS); } /** * Asserts that the value of a property of an object is equal to the given value. *

* Bean notation can be used to specify inner properties. Eg myArray[2].innerValue. * assertReflectionEquals is used to check whether both values are equal. *

* The comparator modes determine how strict to compare the values. * * @param message a message for when the assertion fails * @param propertyName the property, not null * @param expectedPropertyValue the expected value * @param actualObject the object that contains the property * @param modes the comparator modes * @throws AssertionFailedError when both objects are not equals */ public static void assertPropertyReflectionEquals(String message, String propertyName, Object expectedPropertyValue, Object actualObject, ReflectionComparatorMode... modes) throws AssertionFailedError { assertNotNull("Actual object is null.", actualObject); Object propertyValue = getProperty(actualObject, propertyName); String formattedMessage = formatMessage(message, "Incorrect value for property: " + propertyName); assertReflectionEquals(formattedMessage, expectedPropertyValue, propertyValue, modes); } /** * Asserts that a property of all objects in the collection are equal to the given values. *

* Example: assertPropertyEquals("id", myIdCollection, myObjectCollection) checks whether all values of the * id field of the myObjectCollection elements matches the values in the myIdCollection *

* Bean notation can be used to specify inner properties. Eg myArray[2].innerValue. * assertReflectionEquals is used to check whether both values are equal. *

* This is identical to assertPropertyReflectionEquals with * lenient order and ignore defaults set as comparator modes. * * @param propertyName the property, not null * @param expectedPropertyValues the expected values * @param actualObjects the objects that contain the property * @throws AssertionFailedError when both objects are not equals */ public static void assertPropertyLenientEquals(String propertyName, Collection expectedPropertyValues, Collection actualObjects) throws AssertionFailedError { assertPropertyLenientEquals(null, propertyName, expectedPropertyValues, actualObjects); } /** * Asserts that a property of all objects in the collection are equal to the given values. *

* Example: assertPropertyEquals("id", myIdCollection, myObjectCollection) checks whether all values of the * id field of the myObjectCollection elements matches the values in the myIdCollection *

* Bean notation can be used to specify inner properties. Eg myArray[2].innerValue. * assertReflectionEquals is used to check whether both values are equal. *

* The comparator modes determine how strict to compare the values. * * @param propertyName the property, not null * @param expectedPropertyValues the expected values * @param actualObjects the objects that contain the property * @param modes the comparator modes * @throws AssertionFailedError when both objects are not equals */ public static void assertPropertyReflectionEquals(String propertyName, Collection expectedPropertyValues, Collection actualObjects, ReflectionComparatorMode... modes) throws AssertionFailedError { assertPropertyReflectionEquals(null, propertyName, expectedPropertyValues, actualObjects, modes); } /** * Asserts that a property of all objects in the collection are equal to the given values. *

* Example: assertPropertyEquals("id", myIdCollection, myObjectCollection) checks whether all values of the * id field of the myObjectCollection elements matches the values in the myIdCollection *

* Bean notation can be used to specify inner properties. Eg myArray[2].innerValue. * assertReflectionEquals is used to check whether both values are equal. *

* This is identical to assertPropertyReflectionEquals with * lenient order and ignore defaults set as comparator modes. * * @param message a message for when the assertion fails * @param propertyName the property, not null * @param expectedPropertyValues the expected values, not null * @param actualObjects the objects that contain the property * @throws AssertionFailedError when both objects are not equals */ public static void assertPropertyLenientEquals(String message, String propertyName, Collection expectedPropertyValues, Collection actualObjects) throws AssertionFailedError { assertPropertyReflectionEquals(message, propertyName, expectedPropertyValues, actualObjects, LENIENT_ORDER, IGNORE_DEFAULTS); } /** * All fields are checked for null values (except the static ones). * Private fields are also checked. * This is NOT recursive, only the values of the first object will be checked. * An assertion error will be thrown when a property is null. * * @param message a message for when the assertion fails * @param object the object that will be checked for null values. */ public static void assertPropertiesNotNull(String message, Object object) { Set fields = ReflectionUtils.getAllFields(object.getClass()); for (Field field : fields) { if (!Modifier.isStatic(field.getModifiers())) { String formattedMessage = formatMessage(message, "Property '" + field.getName() + "' in object '" + object.toString() + "' is null "); assertNotNull(formattedMessage, ReflectionUtils.getFieldValue(object, field)); } } } /** * Asserts that a property of all objects in the collection are equal to the given values. *

* Example: assertPropertyEquals("id", myIdCollection, myObjectCollection) checks whether all values of the * id field of the myObjectCollection elements matches the values in the myIdCollection *

* Bean notation can be used to specify inner properties. Eg myArray[2].innerValue. * assertReflectionEquals is used to check whether both values are equal. *

* The comparator modes determine how strict to compare the values. * * @param message a message for when the assertion fails * @param propertyName the property, not null * @param expectedPropertyValues the expected values, not null * @param actualObjects the objects that contain the property * @param modes the comparator modes * @throws AssertionFailedError when both objects are not equals */ public static void assertPropertyReflectionEquals(String message, String propertyName, Collection expectedPropertyValues, Collection actualObjects, ReflectionComparatorMode... modes) throws AssertionFailedError { assertNotNull("Actual object list is null.", actualObjects); Collection actualPropertyValues = CollectionUtils.collect(actualObjects, new OgnlTransformer(propertyName)); assertReflectionEquals(message, expectedPropertyValues, actualPropertyValues, modes); } /** * Formats the exception message. * * @param suppliedMessage the user supplied message * @param specificMessage the reason * @return the formatted message */ protected static String formatMessage(String suppliedMessage, String specificMessage) { if (StringUtils.isEmpty(suppliedMessage)) { return specificMessage; } return suppliedMessage + "\n" + specificMessage; } /** * Evaluates the given OGNL expression, and returns the corresponding property value from the given object. * * @param object The object on which the expression is evaluated * @param ognlExpression The OGNL expression that is evaluated * @return The value for the given OGNL expression */ protected static Object getProperty(Object object, String ognlExpression) { try { OgnlContext ognlContext = new OgnlContext(); ognlContext.setMemberAccess(new DefaultMemberAccess(true)); Object ognlExprObj = Ognl.parseExpression(ognlExpression); return Ognl.getValue(ognlExprObj, ognlContext, object); } catch (OgnlException e) { throw new UnitilsException("Failed to get property value using OGNL expression " + ognlExpression, e); } } /** * A commons collections transformer that takes an object and returns the value of the property that is * specified by the given ognl expression. */ protected static class OgnlTransformer implements Transformer { /* The ognl expression */ private String ognlExpression; /** * Creates a transformer with the given ognl expression. * * @param ognlExpression The expression, not null */ public OgnlTransformer(String ognlExpression) { this.ognlExpression = ognlExpression; } /** * Transforms the given object in the value of the property that is specified by the ognl expression. * * @param object The object * @return The value, null if object was null */ public Object transform(Object object) { if (object == null) { return null; } return getProperty(object, ognlExpression); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy