我也面臨着在過去的這個問題,我完全同意你認爲只爲測試目的實施equals()
和hashCode()
是一種代碼異味。我不使用Hamcrest圖書館,所以我會爲您提供一個自定義的解決方案,我可以在我的項目中成功使用它,並且對於它的用法我很滿意。
public static <E, A> void assertListEquals(BiConsumer<E, A> asserter, List<E> expected, List<A> actual) throws AssertionError {
assertEquals(
"Lists have different sizes. Expected list: " + expected + ", actual list: " + actual,
expected.size(),
actual.size());
for (int i = 0; i < expected.size(); i++) {
try {
asserter.accept(expected.get(i), actual.get(i));
} catch (AssertionError e) {
throw e;
}
}
}
正如您所看到的,BiConsumer用於應用檢查兩個對象相等的邏輯。所以這個必須在測試課上實施。它的優點是您可以在比較兩個對象時定義您感興趣的類的字段。
讓我們看看它的用法: 首先我們有一個自定義類f.e.:人
public class Person {
private String firstName;
private String lastName;
private int age;
public Person(String firstName, String lastName, int age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public int getAge() {
return age;
}
}
然後讓我們看看測試方法:
@Test
public void peopleLiveInTheVillage_findPeople_peopleAreFound() throws Exception {
//Arrange
List<Person> expectedPeople = Arrays.asList(
new Person("Lewis", "Smith", 20),
new Person("Steven", "Richard", 25),
new Person("Richie", "Rich", 30));
//Act
List<Person> actualPeople = sut.findPeople();
//Assert
assertListEquals(
(e, a) -> assertPersonEquals(e, a),
expectedPeople,
actualPeople);
}
private void assertPersonEquals(Person expected, Person actual) {
assertEquals(expected.getFirstName(), actual.getFirstName());
assertEquals(expected.getLastName(), actual.getLastName());
assertEquals(expected.getAge(), actual.getAge());
}
由於我的測試(和TDD)的忠實粉絲,我總是寫噸的測試,所以我總是讓一個輔助方法,我包裝BiConsumer:
private void assertPeopleEqual(List<Person> expectedPeople, List<Person> actualPeople) throws AssertionError {
assertListEquals(
(e, a) -> assertPersonEqual(e, a),
expectedPeople,
actualPeople);
}
我希望這可以幫助,歡呼!
以爲我會補充說,沒有理由不能在'Matcher'的'matchesSafely'方法中使用'ReflectionEquals', –