public final void containsEntry(@Nullable Object key, @Nullable Object value) {
    Map.Entry<@Nullable Object, @Nullable Object> entry = immutableEntry(key, value);
    checkNotNull(actual);
    if (!actual.entrySet().contains(entry)) {
      List<@Nullable Object> keyList = singletonList(key);
      List<@Nullable Object> valueList = singletonList(value);
      if (actual.containsKey(key)) {
        Object actualValue = actual.get(key);
        /*
         * In the case of a null expected or actual value, clarify that the key *is* present and
         * *is* expected to be present. That is, get() isn't returning null to indicate that the key
         * is missing, and the user isn't making an assertion that the key is missing.
         */
        StandardSubjectBuilder check = check("get(%s)", key);
        if (value == null || actualValue == null) {
          check = check.withMessage("key is present but with a different value");
        }
        // See the comment on IterableSubject's use of failEqualityCheckForEqualsWithoutDescription.
        check.that(actualValue).failEqualityCheckForEqualsWithoutDescription(value);
      } else if (hasMatchingToStringPair(actual.keySet(), keyList)) {
        failWithoutActual(
            fact("expected to contain entry", entry),
            fact("an instance of", objectToTypeName(entry)),
            simpleFact("but did not"),
            fact(
                "though it did contain keys",
                countDuplicatesAndAddTypeInfo(
                    retainMatchingToString(actual.keySet(), /* itemsToCheck= */ keyList))),
            fact("full contents", actualCustomStringRepresentationForPackageMembersToCall()));
      } else if (actual.containsValue(value)) {
        Set<@Nullable Object> keys = new LinkedHashSet<>();
        for (Map.Entry<?, ?> actualEntry : actual.entrySet()) {
          if (Objects.equal(actualEntry.getValue(), value)) {
            keys.add(actualEntry.getKey());
          }
        }
        failWithoutActual(
            fact("expected to contain entry", entry),
            simpleFact("but did not"),
            fact("though it did contain keys with that value", keys),
            fact("full contents", actualCustomStringRepresentationForPackageMembersToCall()));
      } else if (hasMatchingToStringPair(actual.values(), valueList)) {
        failWithoutActual(
            fact("expected to contain entry", entry),
            fact("an instance of", objectToTypeName(entry)),
            simpleFact("but did not"),
            fact(
                "though it did contain values",
                countDuplicatesAndAddTypeInfo(
                    retainMatchingToString(actual.values(), /* itemsToCheck= */ valueList))),
            fact("full contents", actualCustomStringRepresentationForPackageMembersToCall()));
      } else {
        failWithActual("expected to contain entry", entry);
      }
    }
  }
@Test
  public void containsEntry_failsWithSameToStringOfValue() {
    // Does not contain the correct key, but does contain a value which matches by toString.
    expectFailureWhenTestingThat(ImmutableMap.of(1, "null")).containsEntry(2, null);
    assertFailureKeys(
        "expected to contain entry",
        "an instance of",
        "but did not",
        "though it did contain values",
        "full contents");
    assertFailureValue("an instance of", "Map.Entry<java.lang.Integer, null type>");
    assertFailureValue("though it did contain values", "[null] (java.lang.String)");
  }