Class Correspondence<A,​E>

    • Method Detail

      • from

        public static <A,​E> Correspondence<A,​E> from​(Correspondence.BinaryPredicate<A,​E> predicate,
                                                                 String description)
        Constructs a Correspondence that compares actual and expected elements using the given binary predicate.

        The correspondence does not support formatting of diffs (see formatDiff(A, E)). You can add that behaviour by calling formattingDiffsUsing(com.google.common.truth.Correspondence.DiffFormatter<? super A, ? super E>).

        Note that, if the data you are asserting about contains nulls, your predicate may be invoked with null arguments. If this causes it to throw a NullPointerException, then your test will fail. (See compare(A, E) for more detail on how exceptions are handled.) In particular, if your predicate is an instance method reference on the actual value (as in the String::contains example below), your test will fail if it sees null actual values.

        Example using an instance method reference:

        
         static final Correspondence<String, String> CONTAINS_SUBSTRING =
             Correspondence.from(String::contains, "contains");
         

        Example using a static method reference:

        
         class MyRecordTestHelper {
           static final Correspondence<MyRecord, MyRecord> EQUIVALENCE =
               Correspondence.from(MyRecordTestHelper::recordsEquivalent, "is equivalent to");
           static boolean recordsEquivalent(@Nullable MyRecord actual, @Nullable MyRecord expected) {
             // code to check whether records should be considered equivalent for testing purposes
           }
         }
         

        Example using a lambda:

        
         static final Correspondence<Object, Class<?>> INSTANCE_OF =
             Correspondence.from((obj, clazz) -> clazz.isInstance(obj), "is an instance of");
         
        Parameters:
        predicate - a Correspondence.BinaryPredicate taking an actual and expected value (in that order) and returning whether the actual value corresponds to the expected value in some way
        description - should fill the gap in a failure message of the form "not true that <some actual element> is an element that <description> <some expected element>", e.g. "contains", "is an instance of", or "is equivalent to"
      • transforming

        public static <A,​E> Correspondence<A,​E> transforming​(Function<A,​? extends E> actualTransform,
                                                                         String description)
        Constructs a Correspondence that compares elements by transforming the actual elements using the given function and testing for equality with the expected elements. If the transformed actual element (i.e. the output of the given function) is null, it will correspond to a null expected element.

        The correspondence does not support formatting of diffs (see formatDiff(A, E)). You can add that behaviour by calling formattingDiffsUsing(com.google.common.truth.Correspondence.DiffFormatter<? super A, ? super E>).

        Note that, if you the data you are asserting about contains null actual values, your function may be invoked with a null argument. If this causes it to throw a NullPointerException, then your test will fail. (See compare(A, E) for more detail on how exceptions are handled.) In particular, this applies if your function is an instance method reference on the actual value (as in the example below). If you want a null actual element to correspond to a null expected element, you must ensure that your function transforms a null input to a null output.

        Example:

        
         static final Correspondence<MyRecord, Integer> HAS_ID =
             Correspondence.transforming(MyRecord::getId, "has an ID of");
         
        This can be used as follows:
        
         assertThat(myRecords).comparingElementsUsing(HAS_ID).containsExactly(123, 456, 789);
         
        Parameters:
        actualTransform - a Function taking an actual value and returning a new value which will be compared with an expected value to determine whether they correspond
        description - should fill the gap in a failure message of the form "not true that <some actual element> is an element that <description> <some expected element>", e.g. "has an ID of"
      • transforming

        public static <A,​E> Correspondence<A,​E> transforming​(Function<A,​?> actualTransform,
                                                                         Function<E,​?> expectedTransform,
                                                                         String description)
        Constructs a Correspondence that compares elements by transforming the actual and the expected elements using the given functions and testing the transformed values for equality. If an actual element is transformed to null, it will correspond to an expected element that is also transformed to null.

        The correspondence does not support formatting of diffs (see formatDiff(A, E)). You can add that behaviour by calling formattingDiffsUsing(com.google.common.truth.Correspondence.DiffFormatter<? super A, ? super E>).

        Note that, if you the data you are asserting about contains null actual or expected values, the appropriate function may be invoked with a null argument. If this causes it to throw a NullPointerException, then your test will fail. (See compare(A, E) for more detail on how exceptions are handled.) In particular, this applies if your function is an instance method reference on the actual or expected value (as in the example below). If you want a null actual element to correspond to a null expected element, you must ensure that your functions both transform a null input to a null output.

        If you want to apply the same function to both the actual and expected elements, just provide the same argument twice.

        Example:

        
         static final Correspondence<MyRequest, MyResponse> SAME_IDS =
             Correspondence.transforming(MyRequest::getId, MyResponse::getId, "has the same ID as");
         
        This can be used as follows:
        
         assertThat(myResponses).comparingElementsUsing(SAME_IDS).containsExactlyElementsIn(myRequests);
         
        Parameters:
        actualTransform - a Function taking an actual value and returning a new value which will be compared with a transformed expected value to determine whether they correspond
        expectedTransform - a Function taking an expected value and returning a new value which will be compared with a transformed actual value
        description - should fill the gap in a failure message of the form "not true that <some actual element> is an element that <description> <some expected element>", e.g. "has the same ID as"
      • formattingDiffsUsing

        public Correspondence<A,​E> formattingDiffsUsing​(Correspondence.DiffFormatter<? super A,​? super E> formatter)
        Returns a new correspondence which is like this one, except that the given formatter may be used to format the difference between a pair of elements that do not correspond.

        Note that, if you the data you are asserting about contains null actual or expected values, the formatter may be invoked with a null argument. If this causes it to throw a NullPointerException, that will be taken to indicate that the values cannot be diffed. (See formatDiff(A, E) for more detail on how exceptions are handled.) If you think null values are likely, it is slightly cleaner to have the formatter return null in that case instead of throwing.

        Example:

        
         class MyRecordTestHelper {
           static final Correspondence<MyRecord, MyRecord> EQUIVALENCE =
               Correspondence.from(MyRecordTestHelper::recordsEquivalent, "is equivalent to")
                   .formattingDiffsUsing(MyRecordTestHelper::formatRecordDiff);
           static boolean recordsEquivalent(@Nullable MyRecord actual, @Nullable MyRecord expected) {
             // code to check whether records should be considered equivalent for testing purposes
           }
           static String formatRecordDiff(@Nullable MyRecord actual, @Nullable MyRecord expected) {
             // code to format the diff between the records
           }
         }
         
      • compare

        public abstract boolean compare​(@Nullable A actual,
                                        @Nullable E expected)
        Returns whether or not the actual value is said to correspond to the expected value for the purposes of this test.

        Exception handling

        Throwing a RuntimeException from this method indicates that this Correspondence cannot compare the given values. Any assertion which encounters such an exception during the course of evaluating its condition must not pass. However, an assertion is not required to invoke this method for every pair of values in its input just in order to check for exceptions, if it is able to evaluate its condition without doing so.

        Conventions for handling exceptions

        (N.B. This section is only really of interest when implementing assertion methods that call compare(A, E), not to users making such assertions in their tests.)

        The only requirement on an assertion is that, if it encounters an exception from this method, it must not pass. The simplest implementation choice is simply to allow the exception to propagate. However, it is normally more helpful to catch the exception and instead fail with a message which includes more information about the assertion in progress and the nature of the failure.

        By convention, an assertion may catch and store the exception and continue evaluating the condition as if the method had returned false instead of throwing. If the assertion's condition does not hold with this alternative behaviour, it may choose to fail with a message that gives details about how the condition does not hold, additionally mentioning that assertions were encountered and giving details about one of the stored exceptions. (See the first example below.) If the assertion's condition does hold with this alternative behaviour, the requirement that the assertion must not pass still applies, so it should fail with a message giving details about one of the stored exceptions. (See the second and third examples below.)

        This behaviour is only a convention and should only be implemented when it makes sense to do so. In particular, in an assertion that has multiple stages, it may be better to only continue evaluation to the end of the current stage, and fail citing a stored exception at the end of the stage, rather than accumulating exceptions through the multiple stages.

        Examples of exception handling

        Suppose that we have the correspondence

        
         static final Correspondence<String, String> CASE_INSENSITIVE_EQUALITY =
             Correspondence.from(String::equalsIgnoreCase, "equals ignoring case"
         }
        whose compare method throws NullPointerException if the actual value is null. The assertion
        
         assertThat(asList(null, "xyz", "abc", "def"))
             .comparingElementsUsing(CASE_INSENSITIVE_EQUALITY)
             .containsExactly("ABC", "DEF", "GHI", "JKL");
         
        may fail saying that the actual iterable contains unexpected values null and xyz and is missing values corresponding to GHI and JKL, which is what it would do if the compare method returned false instead of throwing, and additionally mention the exception. (This is more helpful than allowing the NullPointerException to propagate to the caller, or than failing with only a description of the exception.)

        However, the assertions

        
         assertThat(asList(null, "xyz", "abc", "def"))
             .comparingElementsUsing(CASE_INSENSITIVE_EQUALITY)
             .doesNotContain("MNO");
         
        and
        
         assertThat(asList(null, "xyz", "abc", "def"))
             .comparingElementsUsing(CASE_INSENSITIVE_EQUALITY)
             .doesNotContain(null);
         
        must both fail citing the exception, even though they would pass if the compare method returned false. (Note that, in the latter case at least, it is likely that the test author's intention was not for the test to pass with these values.)
      • formatDiff

        public @Nullable String formatDiff​(@Nullable A actual,
                                           @Nullable E expected)
        Returns a String describing the difference between the actual and expected values, if possible, or null if not.

        The implementation on the Correspondence base class always returns null. To enable diffing, use formattingDiffsUsing(com.google.common.truth.Correspondence.DiffFormatter<? super A, ? super E>) (or override this method in a subclass, but factory methods are recommended over subclassing).

        Assertions should only invoke this with parameters for which compare(A, E) returns false.

        If this throws an exception, that implies that it is not possible to describe the diffs. An assertion will normally only call this method if it has established that its condition does not hold: good practice dictates that, if this method throws, the assertion should catch the exception and continue to describe the original failure as if this method had returned null, mentioning the failure from this method as additional information.

      • toString

        public abstract String toString()
        Returns a description of the correspondence, suitable to fill the gap in a failure message of the form "<some actual element> is an element that ... <some expected element>". Note that this is a fragment of a verb phrase which takes a singular subject.

        Example 1: For a Correspondence<String, Integer> that tests whether the actual string parses to the expected integer, this would return "parses to" to result in a failure message of the form "<some actual string> is an element that parses to <some expected integer>".

        Example 2: For the Correspondence<Number, Number> returns by tolerance(double) this returns "is a finite number within " + tolerance + " of" to result in a failure message of the form "<some actual number> is an element that is a finite number within 0.0001 of <some expected number>".

        Overrides:
        toString in class Object