簡體   English   中英

如何在接口默認方法中對新對象創建進行單元測試?

[英]How to unit test new object creation in interface default method?

接口中有一個默認方法,該方法創建新對象並使用其功能。 所以我需要模擬它。 但是我無法弄清楚,除非做出另一個默認方法來返回新實例。 到目前為止,我曾經制造過處理對象創建的工廠,而不是模擬工廠方法。 但是不能在接口中做到這一點,因為接口不能有實例變量(在這種情況下是工廠)。 還有其他想法嗎? 我想在項目中保持一致,但是現在我有兩種不同的方法來避免在方法中創建對象。 這是一個例子:

public interface ISomeInterface
{
    default Integer callMe( )
    {
        Object someObject = new Object( ); // need to mock this
        Integer result = someObject.finish();
        result = result + 1;

        return result;
    }
}

當我不使用這樣的接口時,我曾經使用工廠來重構代碼。

default Integer callMeNotInterfaceClass( )
{
    Object someObject = new Object( );
    Integer result = instanceFactory.create().finish(); // I can mock create() method 
    result = result + 1;

    return result;
}

我為包裝方法實現的唯一解決方案:

public Integer callMe( )
{
    Object someObject = new Object( );
    Integer result = wrapperMethodCall.finish(); // only solution so far. But now I have 2 different approaches in the project to avoid object creation.
    result = result + 1;

    return result;
}

default Object wrapperMethodCall() {
    return new SomeObject().someMethodsToBeMocked();
}

像往常一樣,單元測試迫使您考慮類的設計。

首先,您應該注意到您有兩種主要的不同類型的對象。

有些對象是值:它們是不可變的,可以存在多個副本中,具有可比性(也具有hashCode )。 這種對象很容易存儲在數據庫中。 如果您了解一點Kotlin,您就會聽說過data classes :就是這樣。

其他一些具有實體語義的對象:它們是可變的,將它們進行比較沒有任何意義,並且通常只有一個副本。 他們是一些事情的對象。

具有實體語義的對象是您需要在單元測試中模擬的對象,而無需模擬值。 要傳遞模擬,必須將這些對象作為構造函數的參數注入到類中。

在您的代碼段中,您在一個函數中創建了一個對象,該對象似乎具有實體的語義(值不能finish任何操作),這就是您遇到問題的原因:您無法進行單元測試,因為您無法嘲笑它實體。

解決方案很簡單:您可以在方法中注入對象:

public interface ISomeInterface
{
    default Integer callMe(Object someObject)
    {
        Integer result = someObject.finish();
        result = result + 1;

        return result;
    }

    ...
}

或者您將對象注入類中:

public interface ISomeInterface
{
    default Integer callMe()
    {
        Integer result = finishObject();
        result = result + 1;

        return result;
    }

    // classes will need an instance of the object to implement this
    Integer finishObject(); 

    ...
}

在這兩種情況下,實現您的接口的類都有責任在調用方法時提供對象本身或返回finish方法的值。

但是請記住:如果在這些類的方法中創建對象,則對它們進行單元測試也將變得困難。 使用工廠模式在靜態方法中創建實體對象,然后將那些對象傳遞給構造函數。

如果遵循以下經驗法則,則對類和方法的單元測試將變得更加容易:當對象具有語義值時,並在更高級別(如果可能的話main )上創建它,並將其作為構造函數或方法的參數傳遞。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM