简体   繁体   中英

FlatExtracting Map with AssertJ 3

I'm using AssertJ 3.11.1 and trying to get rid of Hamcrest completely. I managed so far but I'm having trouble with the following code:

class Foo {
  private final Map<String, String> innerMap;

  Foo(Map<String, String> innerMap) {
    this.innerMap = innerMap;
  }

  public Map<String, String> getInnerMap() {
    return this.innerMap;
  }

}

Map<String, String> innerMap = new HashMap<>();
innerMap.put("key1", "value1");
innerMap.put("key2", "value2");

Foo foo = new Foo(innerMap);

Map<Foo, String> map = new HashMap<>();
map.put(foo, "notUsed");

With Hamcrest, I can easily do:

assertThat(metrics,
  hasKey(
    hasProperty("innerMap",
        allOf(hasEntry("key1", "value1"), hasEntry("key2", "value2")))));

However, there's no easy translation to AssertJ. My best approach so far has been something like this (Java 8):

assertThat(metrics.keySet().stream().map(Foo::getInnerMap))
    .flatExtracting(Map::entrySet)
    .contains(entry("key1", "value1"), entry("key2", "value2"));

But this code is not nearly as descriptive as with Hamcrest not to mention that I get an Unchecked generic array creation for varargs parameter compilation warning.

Is there a better way to do it? I'm willing to implement my own custom assertion and perhaps use hasKeySatisfying() from AbstractMapAssert if that's necessary for a cleaner code.

I know that I can use HamcrestCondition but I would rather not use Hamcrest at all.

Thanks in advance!

EDIT:

For now, I came up with this:

public class ExtendedMapAssert<K, V> extends MapAssert<K, V> {

  ExtendedMapAssert(final Map<K, V> actual) {
    super(actual);
  }

  public ExtendedMapAssert<K, V> hasAnyKeySatisfying(final Consumer<K> consumer) {
    isNotNull();

    assertThat(actual.keySet()).isNotEmpty().anySatisfy(consumer);

    return this;
  }
}

public static <K, V> ExtendedMapAssert<K, V> assertThatMap(final Map<K, V> map) {
  return new ExtendedMapAssert<>(map);
}

And then use it like:

assertThatMap(metrics)
  .hasAnyKeySatisfying(
    metricId ->
      assertThat(metricId.getTags())
        .contains(entry("key1", "value1"), entry("key2", "value2")));

Any other ideas?

You could try hasKeySatisfying and build a Condition with a lambda (there is no similar assertion that would take a Consumer yet but contributions are welcomed!) or take an approach you suggested but in a simpler way:

// assertion fails for empty collections no need to use isNotEmpty
assertThat(metrics.keySet()).anySatisfy(metricId ->
  assertThat(metricId.getTags()).contains(entry("key1", "value1"), entry("key2", "value2"))); 

Hope it helps ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM