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

com.fitbur.assertj.error.ShouldBeEqual Maven / Gradle / Ivy

There is a newer version: 1.0.0
Show newest version
/**
 * 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.
 *
 * Copyright 2012-2016 the original author or authors.
 */
package com.fitbur.assertj.error;

import com.fitbur.assertj.description.Description;
import com.fitbur.assertj.internal.ComparatorBasedComparisonStrategy;
import com.fitbur.assertj.internal.ComparisonStrategy;
import com.fitbur.assertj.internal.Failures;
import com.fitbur.assertj.internal.StandardComparisonStrategy;
import com.fitbur.assertj.presentation.Representation;
import com.fitbur.assertj.util.VisibleForTesting;

import static java.lang.Integer.toHexString;
import static com.fitbur.assertj.util.Arrays.array;
import static com.fitbur.assertj.util.Objects.*;

/**
 * Creates an {@link AssertionError} indicating that an assertion that verifies that two objects are equal
 * failed.
 * 

* The built {@link AssertionError}'s message differentiates {@link #actual} and {@link #expected} description if their * string representation are the same (e.g. 42 float and 42 double). It also mentions the comparator in case of a custom * comparator is used (instead of equals method). * * @author Alex Ruiz * @author Yvonne Wang * @author Joel Costigliola */ public class ShouldBeEqual implements AssertionErrorFactory { private static final String EXPECTED_BUT_WAS_MESSAGE = "%nExpecting:%n <%s>%nto be equal to:%n <%s>%nbut was not."; private static final String EXPECTED_BUT_WAS_MESSAGE_USING_COMPARATOR = "%nExpecting:%n <%s>%nto be equal to:%n " + "<%s>%n%s but was not."; private static final Class[] MSG_ARG_TYPES = new Class[] { String.class, String.class, String.class }; protected final Object actual; protected final Object expected; @VisibleForTesting final MessageFormatter messageFormatter = MessageFormatter.instance(); private final ComparisonStrategy comparisonStrategy; private Representation representation; @VisibleForTesting ConstructorInvoker constructorInvoker = new ConstructorInvoker(); @VisibleForTesting DescriptionFormatter descriptionFormatter = DescriptionFormatter.instance(); /** * Creates a new {@link ShouldBeEqual}. * * @param actual the actual value in the failed assertion. * @param expected the expected value in the failed assertion. * @return the created {@code AssertionErrorFactory}. */ public static AssertionErrorFactory shouldBeEqual(Object actual, Object expected, Representation representation) { return new ShouldBeEqual(actual, expected, StandardComparisonStrategy.instance(), representation); } /** * Creates a new {@link ShouldBeEqual}. * * @param actual the actual value in the failed assertion. * @param expected the expected value in the failed assertion. * @param comparisonStrategy the {@link ComparisonStrategy} used to compare actual with expected. * @return the created {@code AssertionErrorFactory}. */ public static AssertionErrorFactory shouldBeEqual(Object actual, Object expected, ComparisonStrategy comparisonStrategy, Representation representation) { return new ShouldBeEqual(actual, expected, comparisonStrategy, representation); } @VisibleForTesting ShouldBeEqual(Object actual, Object expected, ComparisonStrategy comparisonStrategy, Representation representation) { this.actual = actual; this.expected = expected; this.comparisonStrategy = comparisonStrategy; this.representation = representation; } /** * Creates an {@link AssertionError} indicating that an assertion that verifies that two objects are * equal failed.
* The {@link AssertionError} message is built so that it differentiates {@link #actual} and * {@link #expected} description in case their string representation are the same (like 42 float and 42 double). *

* If JUnit 4 is in the classpath and the description is standard (no comparator was used and {@link #actual} and * {@link #expected} string representation were differents), this method will instead create a * org.junit.ComparisonFailure that highlights the difference(s) between the expected and actual objects. *

* {@link AssertionError} stack trace won't show AssertJ related elements if {@link Failures} is configured to filter * them (see {@link Failures#setRemoveAssertJRelatedElementsFromStackTrace(boolean)}). * * @param description the description of the failed assertion. * @param representation * @return the created {@code AssertionError}. */ @Override public AssertionError newAssertionError(Description description, Representation representation) { if (actualAndExpectedHaveSameStringRepresentation()) { // Example : actual = 42f and expected = 42d gives actual : "42" and expected : "42" and // JUnit 4 manages this case even worst, it will output something like : // "java.lang.String expected:java.lang.String<42.0> but was: java.lang.String<42.0>" // which does not solve the problem and makes things even more confusing since we lost the fact that 42 was a // float or a double, it is then better to built our own description, with the drawback of not using a // ComparisonFailure (which looks nice in eclipse) return Failures.instance().failure(defaultDetailedErrorMessage(description, representation)); } // only use JUnit error message if comparison strategy was standard, otherwise we need to mention it in the // assertion error message to make it clear to the user it was used. if (comparisonStrategy.isStandard()) { // comparison strategy is standard -> try to build a JUnit ComparisonFailure that is nicely dispayed in IDE. AssertionError error = comparisonFailure(description); // error ==null means that JUnit was not in the classpath if (error != null) return error; } // No JUnit in the classpath => fall back to default error message return Failures.instance().failure(defaultErrorMessage(description, representation)); } private boolean actualAndExpectedHaveSameStringRepresentation() { return areEqual(representation.toStringOf(actual), representation.toStringOf(expected)); } /** * Builds and returns an error message from description using {@link #expected} and {@link #actual} basic * representation. * * @param description the {@link Description} used to build the returned error message * @param representation the {@link com.fitbur.assertj.presentation.Representation} used to build String representation * of object * @return the error message from description using {@link #expected} and {@link #actual} basic representation. */ private String defaultErrorMessage(Description description, Representation representation) { return comparisonStrategy.isStandard() ? messageFormatter.format(description, representation, EXPECTED_BUT_WAS_MESSAGE, actual, expected) : messageFormatter.format(description, representation, EXPECTED_BUT_WAS_MESSAGE_USING_COMPARATOR, actual, expected, comparisonStrategy); } /** * Builds and returns an error message from description using {@link #detailedExpected()} and * {@link #detailedActual()} detailed representation. * * @param description the {@link Description} used to build the returned error message * @param representation the {@link com.fitbur.assertj.presentation.Representation} used to build String representation * of object * @return the error message from description using {@link #detailedExpected()} and {@link #detailedActual()} * detailed representation. */ private String defaultDetailedErrorMessage(Description description, Representation representation) { if (comparisonStrategy instanceof ComparatorBasedComparisonStrategy) return messageFormatter.format(description, representation, EXPECTED_BUT_WAS_MESSAGE_USING_COMPARATOR, detailedActual(), detailedExpected(), comparisonStrategy); return messageFormatter.format(description, representation, EXPECTED_BUT_WAS_MESSAGE, detailedActual(), detailedExpected()); } private AssertionError comparisonFailure(Description description) { try { AssertionError comparisonFailure = newComparisonFailure(descriptionFormatter.format(description).trim()); Failures.instance().removeAssertJRelatedElementsFromStackTraceIfNeeded(comparisonFailure); return comparisonFailure; } catch (Throwable e) { return null; } } private AssertionError newComparisonFailure(String description) throws Exception { Object o = constructorInvoker.newInstance("org.junit.ComparisonFailure", MSG_ARG_TYPES, msgArgs(description)); if (o instanceof AssertionError) return (AssertionError) o; return null; } private Object[] msgArgs(String description) { return array(description, representation.toStringOf(expected), representation.toStringOf(actual)); } private String detailedToStringOf(Object obj) { return representation.toStringOf(obj) + " (" + obj.getClass().getSimpleName() + "@" + toHexString(obj.hashCode()) + ")"; } private String detailedActual() { return detailedToStringOf(actual); } private String detailedExpected() { return detailedToStringOf(expected); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null) return false; if (getClass() != o.getClass()) return false; ShouldBeEqual other = (ShouldBeEqual) o; if (!areEqual(actual, other.actual)) return false; return areEqual(expected, other.expected); } @Override public int hashCode() { int result = 1; result = HASH_CODE_PRIME * result + hashCodeFor(actual); result = HASH_CODE_PRIME * result + hashCodeFor(expected); return result; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy