断言列表中包含具有特定属性的元素,顺序不限。

3

在Junit5中,我经常使用以下代码段来测试集合是否包含满足特定条件的元素:

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))
        )
    ));

我还没有找到一种在kotest中表达这个意思的方式。我尝试了shouldContainExactlyInAnyOrder等方法,但它们都期望一个实际的对象。我不知道如何表达我想要对每个元素使用不同的匹配器进行测试。

我还查看了检查器,这可能是解决方案,但它们似乎只能帮助对列表中的所有元素进行断言。

2个回答

5
"

Kotest Inspectors可能是您正在寻找的内容。它们允许测试集合中所有,无任何或特定数量的元素是否满足特定断言。

如果没有地址引用数据类型的知识,我会假设您的示例可以像这样转换为Kotest:

"
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
        }
    }
}

@LeoColman指出,withClueassertSoftly不是必需品:

  • withClue只是在断言失败时将给定的提示作为附加信息添加到断言错误消息中。
  • assertSoftly让它内部的所有断言都运行,而不是在第一个失败的断言停止。这意味着,如果我们有一个包含3个元素的集合,我们仍然可以得到关于是否存在具有id "abc"role SENDER的元素的信息。

1
这几乎可以得到与JUnit5+Hamcrest一样好的结果。后者会说类似于“属性id应该是abc,但实际上是xyz”,而Kotest会说“xyz应该是abc”。可以通过在每个it.property shouldBe周围添加嵌套的withClue调用来修复它,但这会使代码有点臃肿。 - Klitos Kyriacou
1
感谢您的回答,我非常喜欢这个解决方案,特别是我不再需要将属性名称作为字符串使用。 - Chris

1

如@Karsten所建议的,使用检查器似乎是这里的正确方法!

如果您想使代码更小,我提供了一种更简单的方法来进行相同的断言:

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

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

withClueassertSoftly都是可选项。


1
感谢指出。我已相应地扩展了我的答案。 - Karsten Gabriel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接