Class FailureMetadata


  • public final class FailureMetadata
    extends java.lang.Object
    An opaque, immutable object containing state from the previous calls in the fluent assertion chain. It appears primarily as a parameter to Subject constructors (and Subject.Factory methods), which should pass it to the superclass constructor and not otherwise use or store it. In particular, users should not attempt to call Subject constructors or Subject.Factory methods directly. Instead, they should use the appropriate factory method:
    • If you're writing a test: Truth.assertAbout(Subject.Factory).that(...)
    • If you're creating a derived subject from within another subject: check(...).about(...).that(...)
    • If you're testing your subject to verify that assertions fail when they should: ExpectFailure

    (One exception: Implementations of CustomSubjectBuilder do directly call constructors, using their CustomSubjectBuilder.metadata() method to get an instance to pass to the constructor.)

    • Method Detail

      • updateForSubject

        FailureMetadata updateForSubject​(Subject subject)
        Returns a new instance that includes the given subject in its chain of values. Truth users do not need to call this method directly; Truth automatically accumulates context, starting from the initial that(...) call and continuing into any chained calls, like ThrowableSubject.hasMessageThat().
      • withMessage

        FailureMetadata withMessage​(java.lang.String format,
                                    java.lang.Object[] args)
        Returns a new instance whose failures will contain the given message. The way for Truth users to set a message is check(...).withMessage(...).that(...) (for calls from within a Subject) or Truth.assertWithMessage(java.lang.String) (for most other calls).
      • failEqualityCheck

        void failEqualityCheck​(com.google.common.collect.ImmutableList<Fact> headFacts,
                               com.google.common.collect.ImmutableList<Fact> tailFacts,
                               java.lang.String expected,
                               java.lang.String actual)
      • fail

        void fail​(com.google.common.collect.ImmutableList<Fact> facts)
      • doFail

        private void doFail​(java.lang.AssertionError failure)
      • description

        private com.google.common.collect.ImmutableList<Fact> description()
        Returns a description of the final actual value, if it appears "interesting" enough to show. The description is considered interesting if the chain of derived subjects ends with at least one derivation that we have a name for. It's also considered interesting in the absence of derived subjects if we inferred a name for the root actual value from the bytecode.

        We don't want to say: "value of string: expected [foo] but was [bar]" (OK, we might still decide to say this, but for now, we don't.)

        We do want to say: "value of throwable.getMessage(): expected [foo] but was [bar]"

        We also want to say: "value of getLogMessages(): expected not to be empty"

        To support that, descriptionIsInteresting tracks whether we've been given context through check calls that include names or, initially, whether we inferred a name for the root actual value from the bytecode.

        If we're missing a naming function halfway through, we have to reset: We don't want to claim that the value is "foo.bar.baz" when it's "foo.bar.somethingelse.baz." We have to go back to "object.baz." (But note that rootUnlessThrowable() will still provide the value of the root foo to the user as long as we had at least one naming function: We might not know the root's exact relationship to the final object, but we know it's some object "different enough" to be worth displaying.)

      • rootUnlessThrowable

        private com.google.common.collect.ImmutableList<Fact> rootUnlessThrowable()
        Returns the root actual value, if we know it's "different enough" from the final actual value.

        We don't want to say: "expected [foo] but was [bar]. string: [bar]"

        We do want to say: "expected [foo] but was [bar]. myObject: MyObject[string=bar, i=0]"

        To support that, seenDerivation tracks whether we've seen multiple actual values, which is equivalent to whether we've seen multiple Subject instances or, more informally, whether the user is making a chained assertion.

        There's one wrinkle: Sometimes chaining doesn't add information. This is often true with "internal" chaining, like when StreamSubject internally creates an IterableSubject to delegate to. The two subjects' string representations will be identical (or, in some cases, _almost_ identical), so there is no value in showing both. In such cases, implementations can call the no-arg checkNoNeedToDisplayBothValues(), which sets valuesAreSimilar, instructing this method that that particular chain link "doesn't count." (Note also that there are some edge cases that we're not sure how to handle yet, for which we might introduce additional check-like methods someday.)

      • rootCause

        private java.lang.Throwable rootCause()
        Returns the first Throwable in the chain of actual values. Typically, we'll have a root cause only if the assertion chain contains a ThrowableSubject.