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;
}
@Override
public 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