[英]Correct unit testing property holder with no equals implementation
我正在與一位同事就我遇到的特定情況進行辯論,如果有人可以出於某種觀點或理論基礎而陷入困境,那將是非常棒的。
假設我們有一個類型為A的模型對象。它們是Java Bean,屬性持有者,並且具有諸如getPrice,getQuantity,getName等方法。
我們還假設由於某些傳統原因,equals方法在兩個不同的對象上返回true,即使它們具有不同的屬性值!
我將提供一些代碼來說明這個問題。 (顯然不一樣的代碼,取了捷徑)
class A {
private final double q;
private final double p;
public A(double q, double p) {
this.q = q;
this.p = p;
}
public double getQuantity()
{
return q;
}
public double getPrice()
{
return p;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
// not the actual method but a.equals(aWithDifferentValues) is True
// this is the crux of the problem
return true;
}
}
public abstract class Handler {
protected Manager m;
public Handler(Manager m) {
this.m = m;
}
abstract public void handle(A a);
}
class HandlerA extends Handler {
public HandlerA(Manager m) {
super(m);
}
@Override
public void handle(A a) {
m.f(a, "abc");
}
}
...
class HandlerC extends Handler {
public HandlerC(Manager m) {
super(m);
}
@Override
public void handle(A a) {
m.g(a, 1);
}
}
class Manager {
public void f(A a, String s) { }
public void g(A a, double q) { }
}
我們要對HandlerA進行單元測試。
因此,我們可能想編寫如下測試:
public class TestMain {
@Test
public void givenA_fHappens() {
Manager manager = mock(Manager.class);
HandlerA handler = new HandlerA(manager);
A givenA = new A(7, 9);
handler.handle(givenA);
verify(manager).f(givenA, "abc");
}
}
現在的問題是,由於equals返回true,因此對於具有不同屬性的另一個A對象,需要在代碼中進行此修改:
@Override
public void handle(A a) {
-- m.f(a, "abc");
++ m.f(new A(1, 1), "abc");
}
不會包含在單元測試中
我建議我們在驗證中使用匹配器(或斷言存在參數捕獲器的地方),實際上已經存在一個可以服務的名為SamePropertyValueAs的匹配器,但是我遭到批評,因為我們不想斷言它們具有相同的值,只是代碼被調用。
你怎么看? 您對此有何看法?
答案實際上取決於您要測試的內容。 基於此,答案將有所不同。
你測試一個通過實例中所報告的意義相同 equals
方法? 如果是這樣,那么verify(manager).f(givenA, "abc")
就足夠了(只要您相信已經為給定的類實現了對象相等性)。 在大多數情況下,這是可取的,因為從語義上講更有意義,並且我們不想擔心諸如對象引用相等之類的底層細節。 在上面的示例中,理想情況下, equals
方法應該是固定的:)
您是否正在測試是否將相同的對象引用傳遞給該方法? 在某些情況下,我們可能希望顯式檢查傳遞的對象確實是內部使用的相同引用,而不是被等效外觀的對象替代。 這很少見,但是如果有此需要,請使用ArgumentCaptor
並聲明已發送值和捕獲值之間的引用相等性。
到您提到的地步, 我們不想斷言它們具有相同的值,只需要調用代碼即可 。
我個人並不認為斷言該方法已被調用就足夠了。 如果傳遞的值不同(如您提到的值),該怎么辦。 這會使測試不完整並使代碼變脆。 這樣的測試只會使覆蓋率報告看起來綠色,但缺乏完整的功能覆蓋率。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.