[java] 使用Mockito測試抽像類



3 Answers

如果你只需要測試一些具體的方法而不觸及任何摘要,你可以使用CALLS_REAL_METHODS (參見Morten的答案 ),但是如果被測試的具體方法調用某些摘要或者未實現的接口方法,工作 - Mockito會抱怨“無法在java界面上調用真正的方法。”

(是的,這是一個糟糕的設計,但是一些框架,例如Tapestry 4,會對你施加壓力。)

解決方法是顛倒這種方法 - 使用普通的模擬行為(即所有的模擬/存根)和使用doCallRealMethod()明確地調用被測試的具體方法。 例如

public abstract class MyClass {
    @SomeDependencyInjectionOrSomething
    public abstract MyDependency getDependency();

    public void myMethod() {
        MyDependency dep = getDependency();
        dep.doSomething();
    }
}

public class MyClassTest {
    @Test
    public void myMethodDoesSomethingWithDependency() {
        MyDependency theDependency = mock(MyDependency.class);

        MyClass myInstance = mock(MyClass.class);

        // can't do this with CALLS_REAL_METHODS
        when(myInstance.getDependency()).thenReturn(theDependency);

        doCallRealMethod().when(myInstance).myMethod();
        myInstance.myMethod();

        verify(theDependency, times(1)).doSomething();
    }
}

更新後添加:

對於非void方法,您需要使用thenCallRealMethod() ,例如:

when(myInstance.myNonVoidMethod(someArgument)).thenCallRealMethod();

否則Mockito會抱怨“檢測到未完成的殘片”。

Question

我想測試一個抽像類。 當然,我可以手動編寫一個從類繼承的模擬

我可以使用模擬框架(我正在使用Mockito)而不是手工製作模擬器嗎? 怎麼樣?




您可以在測試中用匿名類擴展抽像類。 例如(使用Junit 4):

private AbstractClassName classToTest;

@Before
public void preTestSetup()
{
    classToTest = new AbstractClassName() { };
}

// Test the AbstractClassName methods.



模擬框架旨在讓您更容易地模擬出您正在測試的類的依賴關係。 當你使用模擬框架來模擬一個類時,大多數框架都會動態地創建一個子類,並用代碼來替換方法實現,以檢測何時調用方法並返回一個假值。

當測試一個抽像類時,你想執行被測主體(SUT)的非抽象方法,所以一個模擬框架不是你想要的。

部分的困惑是,你所關聯問題的答案是手工製作一個從你的抽像類延伸出來的模擬。 我不會嘲笑這樣的班級。 模擬是一個用來替代依賴關係的類,可以根據期望進行編程,並且可以查詢是否滿足這些期望。

相反,我建議在測試中定義抽像類的非抽象子類。 如果這樣會導致代碼太多,那麼這可能表明您的課程難以擴展。

另一種解決方案是將測試用例本身抽像出來,用抽象方法創建SUT(換句話說,測試用例將使用Template Method設計模式)。




真正讓我嘲笑抽像類的事實是,默認的構造函數YourAbstractClass()被調用(在模擬中缺少super()),在Mockito中也沒有任何方式默認初始化模擬屬性(例如List屬性與空的ArrayList或LinkedList)。

我的抽像類(基本上是生成的類源代碼)沒有為列表元素提供依賴關係setter注入,也沒有為它初始化列表元素(我嘗試手動添加)提供構造函數。

只有類屬性使用默認的初始化:private List dep1 = new ArrayList; 私人列表dep2 =新的ArrayList

因此,如果不使用真實的對象實現(例如,單元測試類中的內部類定義,重寫抽象方法)並且窺探真實對象(它會進行適當的字段初始化),就沒有辦法模擬抽像類。

太糟糕了,只有PowerMock會在這裡進一步提供幫助。




Related