assertj_AssertJ的SoftAssertions –我们需要它们吗?

assertj

编写好的单元测试的规则之一是,它应该由于一种原因而失败,因此,单元测试应该测试一种逻辑概念。 有时很难在每个测试中拥有一个断言。 为了遵循规则,我们可能在单个测试中每个对象具有多个断言。

但是,在一个测试中存在多个断言的问题在于,如果第一个断言由于任何原因而失败,我们实际上将不知道其他断言,因为它们将不会被执行。 并且您知道了演练:您检查断言失败原因,进行修复,然后重新运行测试。 也许您很幸运,测试会通过。 但是也许它将因另一个断言而失败。 对于真正快速的单元测试,这不是什么大问题,但是例如,在进行Selenium测试时,分析和故障检测可能会变得很麻烦并且肯定会很费时。

幸运的是,借助AssertJ的SoftAssertions ,我们可以重新考虑在测试中创建断言的SoftAssertions

一个宣称可以统治所有人的主张!

在假设的Dice游戏中,有一个Score对象,其中保存得分值,骰子组合和提醒。 在单元测试中,我们可能想验证不同骰子组合的分数是如何计算的。

在下面的示例中,验证了一个概念(分数对象):

@Test
public void verifiesScore() {
    Score score = Score.scoreBuilder()
                       .withValue(11)
                       .withCombination(dice(1, 1, 3, 4))
                       .withReminder(dice(6))
                       .build();

    assertThat(score.getValue())
        .as("Has score")
        .isEqualTo(8);

    assertThat(score.getCombination())
        .as("Has combination")
        .isEqualTo(dice(1, 1, 3, 3));

    assertThat(score.getReminder())
        .as("Has reminder")
        .isEqualTo(dice(5));
}

如您所见,所有三个断言都失败了,但是由于第一个失败后测试的执行停止,因此我们只会看到第一个失败的结果:

org.junit.ComparisonFailure: [Has score] 
Expected :8
Actual   :11

引入

为了解决这个问题,我们可以使用SoftAssertions ,它将在调用assertAll()方法时立即收集所有断言的结果:

@Test
public void verifiesScoreSoftly() {
    Score score = Score.scoreBuilder()
                       .withValue(11)
                       .withCombination(dice(1, 1, 3, 4))
                       .withReminder(dice(6))
                       .build();

    SoftAssertions softAssertions = new SoftAssertions();

    softAssertions.assertThat(score.getValue())
                  .as("Has score")
                  .isEqualTo(8);
    softAssertions.assertThat(score.getCombination())
                  .as("Has combination")
                  .isEqualTo(dice(1, 1, 3, 3));
    softAssertions.assertThat(score.getReminder())
                  .as("Has reminder")
                  .isEqualTo(dice(5));

    softAssertions.assertAll();
}

现在我们可以验证测试中的所有断言失败:

org.assertj.core.api.SoftAssertionError: 
The following 3 assertions failed:
1) [Has score] expected:<[8]> but was:<[11]>
2) [Has combination] expected:<...alue=3}, Dice{value=[3]}]> but was:<...alue=3}, Dice{value=[4]}]>
3) [Has reminder] expected:<[Dice{value=[5]}]> but was:<[Dice{value=[6]}]>

JUnitSoftAssertions

代替手动创建SoftAssertions并调用其assertAll()我们可以使用JUnit @Rule

@Rule
public JUnitSoftAssertions softAssertions = new JUnitSoftAssertions();

@Test
public void verifiesScoreSoftlyUsingRule() {
    Score score = Score.scoreBuilder()
                       .withValue(11)
                       .withCombination(dice(1, 1, 3, 4))
                       .withReminder(dice(6))
                       .build();

    softAssertions.assertThat(score.getValue())
                  .as("Has score")
                  .isEqualTo(8);
    softAssertions.assertThat(score.getCombination())
                  .as("Has combination")
                  .isEqualTo(dice(1, 1, 3, 3));
    softAssertions.assertThat(score.getReminder())
                  .as("Has reminder")
                  .isEqualTo(dice(5));
}

我们不仅不需要记住调用assertAll()而且还可以在IntelliJ的比较编辑器中看到潜在的失败:

0B0b09VuqaAG8WGxhUUhxdmZfa3M

自定义

为了提高分数验证的可读性和可重用性,我们可以创建一个自定义断言,以便可以按以下方式使用它:

@Test
public void verifiesScoreSoftlyWithCustomAssertion() {

    Score score = Score.scoreBuilder()
                       .withValue(11)
                       .withCombination(dice(1, 1, 3, 4))
                       .withReminder(dice(6))
                       .build();

    SoftScoreAssertion.assertThat(score)
                      .hasValue(8)
                      .hasCombination(dice(1, 1, 3, 3))
                      .hasReminder(dice(5))
                      .assertAll();
}

SoftScoreAssertion使用SoftAssertions ,因此我们仍然会立即看到所有断言错误。 和代码:

class SoftScoreAssertion extends AbstractAssert<SoftScoreAssertion, Score> {

    private SoftAssertions softAssertions = new SoftAssertions();

    protected SoftScoreAssertion(Score actual) {
        super(actual, SoftScoreAssertion.class);
    }

    public static SoftScoreAssertion assertThat(Score actual) {
        return new SoftScoreAssertion(actual);
    }

    public SoftScoreAssertion hasValue(int scoreValue) {
        isNotNull();
        softAssertions.assertThat(actual.getValue())
                      .as("Has score")
                      .isEqualTo(scoreValue);
        return this;
    }

    public SoftScoreAssertion hasReminder(List<Dice> expected) {
        isNotNull();
        softAssertions.assertThat(actual.getReminder())
                      .as("Has reminder")
                      .isEqualTo(expected);
        return this;
    }

   public SoftScoreAssertion hasCombination(List<Dice> expected) {
        isNotNull();
        softAssertions.assertThat(actual.getCombination())
                      .as("Has combination")
                      .isEqualTo(expected);
        return this;
    }

    @Override
    public SoftScoreAssertion isNotNull() {
        softAssertions.assertThat(actual).isNotNull();
        return this;
    }

    public void assertAll() {
        this.softAssertions.assertAll();
    }
}

资源资源

源代码

翻译自: https://www.javacodegeeks.com/2015/09/assertjs-softassertions-do-we-need-them.html

assertj

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值