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的比较编辑器中看到潜在的失败:
自定义
为了提高分数验证的可读性和可重用性,我们可以创建一个自定义断言,以便可以按以下方式使用它:
@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;}@Overridepublic SoftScoreAssertion isNotNull() {softAssertions.assertThat(actual).isNotNull();return this;}public void assertAll() {this.softAssertions.assertAll();}
}
资源资源
- http://joel-costigliola.github.io/assertj/assertj-core-features-highlight.html#soft-assertions
- https://github.com/joel-costigliola/assertj-core/wiki/Creating-specific-assertions
源代码
- 可以在我在GitHub上的unit-testing-demo项目中找到本文的源代码: https : //github.com/kolorobot/unit-testing-demo 。
翻译自: https://www.javacodegeeks.com/2015/09/assertjs-softassertions-do-we-need-them.html
assertj