2012-12-07 23 views
3

http://stackoverflow.com/questions/6645263/unit-testing-overridden-methods-which-call-super(這個問題有類似的措辭,但是是不一樣的)如何對超級調用的重寫方法進行單元測試?

我有事沿行:

public class SuperClass { 
    private int superClassInteger = 2; 

    public void superClassMethod() { 
     superClassInteger = 5; 
    } 

    public int getSuperClassInteger() { 
     return superClassInteger(); 
    } 
} 

然後在我的測試中,我有:

public class SuperClassTest { 
    public void testSuperClassMethod() { 
     SuperClass superClass = new SuperClass(); 
     superClass.superClassMethod(); 
     assertEquals(5, super.getSuperClassInteger()) 
    } 
} 

然後我有一個子類:

public class SubClass { 
    private int subClassInteger = 2; 

    public void subClassMethod() { 
     super.superClassMethod(); 
     subClassInteger = 32; 
    } 

    public int getSuperClassInteger() { 
     subClassInteger; 
    } 
} 

然後我的子類測試:

public class SubClassTest { 
    public void testSubClassMethod() { 
     SubClass subClass = new SubClass(); 
     subClass.subClassMethod(); 
     assertEquals(5, subclass.getSuperClassInteger()); 
     assertEquals(32, subclass.getSubClassInteger()) 
    } 
} 

我的問題是,測試子類的行爲,我反覆測試代碼我有超類。我可以拿出:assertEquals(5, subclass.getSuperClassInteger());,因爲我只是想測試子類的業務邏輯。然而,問題在於如果有人不小心將superClassMethod的呼叫移除,測試仍然會通過。所以我需要確認是否打了一個超級電話。測試這個用例的常用方法是什麼?

注意:我知道組合/戰略模式vs繼承有助於解決這個問題,但爲了解決這個問題,你基本上說我絕不應該重寫一個方法並在我的代碼中調用super(我很難相信將永遠不會被用於)

回答

1

使用JMockit,並檢查了驗證調用超。

JMockit

示例有關此

public void test { 
    SubClass subClass = new SubClass(); 
    subClass.subClassMethod(); 
    new Verifications() { 
    // mock only this method of superClass - and only in this test 
    @Mocked (methods = "superClassMethod") 
    SuperClass superClass; 
    { 
    superClass.superClassMethod(); 
    times = 1; // specify invocation count 
    } 
    }; 

} 
3

這可能不是你想要的,你應該答案(即不是一個解決辦法), 但答案,但你永遠不應該覆蓋的方法和調用超。

我正在做一個遺留項目,做了很多,這是一個噩夢來維護,調試和測試。

相反,它是更好地使用抽象類的模板方法模式:

之前

public class SuperClass<T> { 
    public void include(T t) { 
    validate(T); 
    dao.save(T); 
    } 

    // I've found code like that. 
    public void validate(T t) { 
    } 
} 

public class SubClass1 extends SuperClass<MyClass> { 
    @Override 
    public void include(MyClass mc) { 
    doStuff(mc); 
    doMoreStuff(mc); 
    super.include(mc); 
    } 

    @Override 
    public void validate(MyClass mc) { 
    doValidationStuff(); 
    } 
} 

public class SubClass2 extends SuperClass<AnotherClass> { 
    @Override 
    public void include(AnotherClass ac) { 
    doDifferentStuff(); 
    super.include(mc); 
    } 
} 

public abstract class AbstractClass<T> { 
    abstract void validate(T t); 

    // this method can now be tested 
    public void include(T t) { 
    validate(T); 
    dao.save(T); 
    } 
} 

public class Class1 extends AbstractClass<MyClass> { 
    public void validate(MyClass mc) { 
    doValidationStuff(); 
    doStuff(mc); 
    doMoreStuff(mc); 
    } 
} 

public class Class2 extends AbstractClass<AnotherClass> { 
    public void validate(AnotherClass ac) { 
    doDifferentStuff(); 
    } 
} 

後,你可以看到,這個重構簡化了維護和測試,您不必擔心必須模擬Class1和Class2測試中的超類方法調用,並且該代碼已關閉以進行修改並打開擴展離子即更易於維護。

+1

這是對大多數情況的合理建議,但有時候,特別是在處理第三方API時,調用'super()'是不可避免的。 (至少沒有很多麻煩) – biziclop

+0

在這種情況下,我想最好是在超級調用之前調用overriden方法中的其他方法,然後測試它們。 – Tarek

相關問題