Search code examples
javaguavaassertj

Compare maps ignoring given fields


I feel like I'm missing something obvious here, but the documentation is letting me down. I'm attempting to compare two maps while ignoring a set of fields in assertJ. I would like to see this assert pass:

  private static final String[] IGNORED_FIELDS = { "ignored", "another" };
  private static final Map<String, Object> TEST_PAYLOAD = ImmutableMap.of("test", "payload", "example", "value", "ignored", "field");
  private static final Map<String, Object> COMPARISON_PAYLOAD = ImmutableMap.of("test", "payload", "example", "value", "another", "ignored field");
  // assert fails
  assertThat(TEST_PAYLOAD).isEqualToIgnoringGivenFields(COMPARISON_PAYLOAD, IGNORED_FIELDS);

However, the comparison that actually occurs is of the map objects, and fails on things like size, modCount, threshold, etc. In addition, it doesn't actually ignore the fields listed when comparing tables, keys, and values. I have also tried using

  assertThat(TEST_PAYLOAD).usingRecursiveComparison().ignoringGivenFields(IGNORED_FIELDS).isEqualTo(COMPARISON_PAYLOAD);

but this failed because it attempted to compare the ignored fields. Is there an elegant solution here, or am I going to have to manually iterate through keys?


Solution

  • ignoringGivenFields() won't work, because it's an ObjectAssert, not a MapAssert method and operates on object's properties, not map's keys, as you pointed out.

    That said, I believe there's no built-in AssertJ method which you could use, but you can write your own filter method and apply it before doing equality test:

    private static <V> Map<String, V> filterIgnoredKeys(Map<String, V> map) {
        return Maps.filterKeys(map, key -> !IGNORED_FIELDS.contains(key));
    }
    // later
    assertThat(filterIgnoredKeys(TEST_PAYLOAD))
            .isEqualTo(filterIgnoredKeys(COMPARISON_PAYLOAD))
    

    If you want the solution to be more elegant, you can experiment with your own custom assertion.