JUnit `assertEquals/assertTrue` 導致測試代碼充斥底層細節,重複代碼多、錯誤訊息不明確(如 `Expected: 1343044800000 Actual: 1343041200000`),難以表達業務意圖。
assertThat(myDouble).isLessThanOrEqualTo(2.0);
assertThat(myList).contains("a");
assertThat("text").isNotEmpty().startsWith("some").hasLength(9); // 鏈式

public class RangeAssert extends ListAssert {
protected RangeAssert(List actual) { super(actual); }
public static RangeAssert assertThat(List actual) { return new RangeAssert(actual); }
public RangeAssert hasSize(int expected) {
isNotNull();
Assertions.assertThat(actual.size()).as("range count").isEqualTo(expected);
return this;
}
public RangeAssert isSortedAscending() { ... return this; }
public RangeAssert hasRange(String from, String to) {
isNotNull();
boolean found = actual.stream().anyMatch(r -> r.getStart()==fromTime && r.getEnd()==toTime);
Assertions.assertThat(found)
.overridingErrorMessage("ranges %s do not contain %s-%s", actual, from, to)
.isTrue();
return this;
}
}
// 原始:大量 assertEquals
// 自定義斷言:
RangeAssert.assertThat(ranges)
.hasSize(3)
.isSortedAscending()
.hasRange("2012-07-23 12:00", "2012-07-23 13:00")
.hasRange("2012-07-23 13:00", "2012-07-23 14:00")
.hasRange("2012-07-23 14:00", "2012-07-23 15:00");
錯誤訊息變為:`ranges [Range{12:00-13:00}, ...] do not contain 2012-07-23 16:00-2012-07-23 14:00`,業務語義清晰。
自定義斷言成本低、收益高,是測試代碼從「能跑」進化為「可讀、可維護」的關鍵一步。
出處:bianceng.cn