0

I have a map in which its values are a simple pojo. For example (in a very loosely code):

Class Data{
  int a;
  Boolean b;
}

Map<Integer, Data> myMap = new HashMap<>();

Now the map is being populated with values. And at then end I would like to assert that all the b values of the data object of all map entries are, for example, true.

So I tried something like that:

private void computeAllBooleans(){

    allBooleansStatus = true;
    myMap.values()
        .forEach(data ->
            allBooleansStatus = allBooleansStatus && data.getB();
}
  1. Is there a more concise way to achieve that?
  2. Is there a way to assert it with JUnit (or other relevant frameworks like hamcrest, assertj, etc.) assertions?

(I noticed this link but didn't understand how can I use the suggested answers there...)

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
dushkin
  • 1,939
  • 3
  • 37
  • 82
  • 1
    Probably you need to use `allMatch` like this: `myMap.values().stream().allMatch(data ->data.getB().equals(true));` – Hadi J Jan 11 '22 at 15:01

3 Answers3

3

With AssertJ Core you can chain extracting and containsOnly:

Map<Integer, Data> myMap = new HashMap<>();
myMap.put(1, new Data(1, true));
myMap.put(2, new Data(2, true));
myMap.put(3, new Data(3, true));

assertThat(myMap.values()).extracting(Data::getB).containsOnly(true);

The benefit of using AssertJ is also a nicely formatted error message in case of failures. For example, the following:

Map<Integer, Data> myMap = new HashMap<>();
myMap.put(1, new Data(1, true));
myMap.put(2, new Data(2, false));
myMap.put(3, new Data(3, false));

assertThat(myMap.values()).extracting(Data::getB).containsOnly(true);

would fail with:

java.lang.AssertionError: 
Expecting ArrayList:
  [true, false, false]
to contain only:
  [true]
but the following element(s) were unexpected:
  [false, false]

More Iterable assertions are described in the official documentation.

Stefano Cordio
  • 1,687
  • 10
  • 20
2

you can use more elegant way with the assertj library using allMatch or allSatisfy:

https://assertj.github.io/doc/#assertj-core-group-satisfy

List<TolkienCharacter> hobbits = list(frodo, sam, pippin);

// all elements must satisfy the given assertions
assertThat(hobbits).allSatisfy(character -> {
  assertThat(character.getRace()).isEqualTo(HOBBIT);
  assertThat(character.getName()).isNotEqualTo("Sauron");
});
Medamine
  • 129
  • 6
0

You can use allMatch terminal operation to check all element of map like this:

myMap.values().stream().allMatch(Data::getB);

or use filter and count it like this:

myMap.values().stream().filter(Data::getB).count() == myMap.size();
Hadi J
  • 16,989
  • 4
  • 36
  • 62
  • 2
    Of course you have to place this code inside an `assert` call: `assertTrue( myMap.values().stream().allMatch( Data::getB ) )`. For the second approach, it has to be done accordingly. – tquadrat Jan 11 '22 at 15:40
  • 3
    Or `myMap.values().forEach(data -> assertTrue(data.getB()) );` – Holger Jan 11 '22 at 16:10
  • 1
    Better use AssertJ `allMatch` in this case: https://www.javadoc.io/doc/org.assertj/assertj-core/latest/org/assertj/core/api/AbstractIterableAssert.html#allMatch(java.util.function.Predicate,java.lang.String) – Joel Costigliola Jan 12 '22 at 21:02
  • Using AssertJ is much preferable. Code is cleaner and assertion error messages are way more descriptive. – Viktar Patotski Jun 27 '22 at 22:11