Home > other >  Assert that list contains elements with specific properties in any order
Assert that list contains elements with specific properties in any order

Time:08-18

In Junit5 i used the following snippet often to test if a collection contains elements that fullfill certain criteria:

assertThat("The list of addresses", addresses.getAddressReferences(), containsInAnyOrder(
        allOf(
            hasProperty("id", is("abc")),
            hasProperty("role", is(SENDER))
        ),
        allOf(
            hasProperty("id", is("def")),
            hasProperty("role", is(RECEIVER))
        )
    ));

I did not yet find a way to express this in kotest I tried shouldContainExactlyInAnyOrder and such but they expect an actual object. I don't know how to express that i want to test each element against a different matcher.

I also checked the inspectors which might be the solution but they only seem to help to make assertions on ALL elements in the list at once.

CodePudding user response:

Kotest Inspectors might be what you are looking for. They allow to test that all, none, or a specific number of elements in a collection satisfy specific assertions.

Without knowledge of the address references data types I would assume that your example can be translated to Kotest like this:

withClue("The list of addresses") {
    val references = addresses.getAddressReferences()
    assertSoftly {
        references shouldHaveSize 2
        references.forOne {
            it.id shouldBe "abc"
            it.role shouldBe SENDER
        }
        references.forOne {
            it.id shouldBe "def"
            it.role shouldBe RECEIVER
        }
    }
}

As pointed out by @LeoColman, the withClue and assertSoftly are not mandatory:

  • withClue just adds the given clue as additional info to the assertion error message in case an assertion fails.
  • assertSoftly lets all of the assertions inside it run instead of stopping at the first failed assertion. This means that if we have for instance a collection of 3 elements, we still get information about the fact that there is or is not an element with id "abc" and role SENDER.

CodePudding user response:

Using inspectors as suggested by @Karsten seems like the way here!

I present a simpler way to make the same assertions if you want to keep the code smaller:

val references = addresses.getAddressReferences()
references.forOne {
    it.id shouldBe "abc"
    it.role shouldBe SENDER
}

references.forOne {
    it.id shouldBe "def"
    it.role shouldBe RECEIVER
}

Both withClue and assertSoftly are optional

  • Related