JUnit5:如何通过单个assert调用来声明对象的几个属性?

Sas*_*ota 5 java junit hamcrest assertj junit5

我想用一个assert声明一个对象的几个属性。

使用JUnit 4和Hamcrest,我将编写如下内容:

assertThat(product, allOf(
        hasProperty("name", is("Coat")),
        hasProperty("available", is(true)),
        hasProperty("amount", is(12)),
        hasProperty("price", is(new BigDecimal("88.0")))
));
Run Code Online (Sandbox Code Playgroud)

问:如何使用JUnit 5和AssertJ在一个断言调用中断言几个属性?或者,在JUnit 5 Universe中,这样做的最佳方法是什么。

注意:我当然可以创建具有所有所需属性的对象并执行

assertThat(actualProduct, is(expectedProduct))
Run Code Online (Sandbox Code Playgroud)

但这不是重点。

Ste*_*dio 11

With AssertJ, another option would be to use returns():

assertThat(product)
    .returns("Coat", from(Product::getName)),
    .returns(true, from(Product::getAvailable)),
    .returns(12, from(Product::getAmount)),
    .returns(new BigDecimal("88.0"), from(Product::getPrice));
Run Code Online (Sandbox Code Playgroud)

有点冗长,但我发现与extracting/相比更容易阅读contains

请注意,这from()只是用于提高可读性的可选语法糖。

  • 非常有趣的替代方案(+1)。我不知道。IHMO,对于需要断言许多属性的对象来说,这是有道理的。对于其他情况,可能更少。请注意,“from”是可选的。这是一个阅读标记。 (3认同)

dav*_*xxx 9

使用AssertJ,最接近的是:

assertThat(product).extracting("name", "available", "amount", "price")
                   .containsExactly("Coat", true, 12, new BigDecimal("88.0"));
Run Code Online (Sandbox Code Playgroud)

但是我不喜欢用Strings 来引用字段名称,因为它们仅作为字段名称的有效性才在运行时检查(反射的已知问题),而且String在我们从IDE执行的重构操作过程中,也可能会错误地更新这些s。

虽然有点冗长,但我更喜欢:

assertThat(product).extracting(Product::getName, Product::getAvailable, 
                               Product::getAmount, Product::getPrice)
                   .containsExactly("Coat", true, 12, new BigDecimal("88.0"));
Run Code Online (Sandbox Code Playgroud)

与您引用的Hamcrest相比,AssertJ的优势在于它确实很流利:因此在大多数情况下,您需要一次导入:import org.assertj.core.api.Assertions;并且对于集合断言而言,有时:org.assertj.core.groups.Tuple;

这里是JUnit 5或4; 这并不重要,因为在非常简单的情况下,您仅将JUnit用作测试运行器,而让AssertJ来执行断言。

或者,在JUnit 5 Universe中,这样做的最佳方法是什么。

JUnit 5(作为第4版)不提供灵活灵活的断言功能。因此,使用JUnit 5的最佳方法进行操作必然会产生更多的样板代码:equals()/hashCode()出于公平原因,要断言或要覆盖的字段数量与断言一样多。


joh*_*ink 5

你可以使用Assertions.assertAll

assertAll("product",
   () -> assertEquals("Coat", product.getName()),
   () -> assertTrue(product.isAvaikable())
);
Run Code Online (Sandbox Code Playgroud)

assertAll 可以接受任意多的单个断言。这是用户指南中该部分的链接:https : //junit.org/junit5/docs/current/user-guide/#writing-tests-assertions