簡體   English   中英

在抽象類中模擬新對象實例

[英]Mock a New Object instance in a Abstract Class

我有一個AbstractDao類,在其中實例化Rest Fore API。 我無法在Power Mock中模擬新的forceAPI(config)。 請提出建議。

public abstract class AbstractDao {

@Inject
private Configuration configuration;

public ForceApi getForceAPI() {
    ApiConfig config = new ApiConfig();
    config.setClientId("test");
    config.setClientSecret("test");
    config.setUsername("test");
    config.setPassword("test");
    config.setLoginEndpoint("test");
    return new ForceApi(config);
}

}

我正在嘗試以這種方式進行操作,但無法正常工作。 我的DAO課正在擴展Abstract DAO課

@RunWith(BlockJUnit4ClassRunner.class)
public class SalesForceDaoImplTest {

@InjectMocks
private SalesForceDaoImpl salesForceDao;
@Mock
private ForceApi forceApiMock;
@Mock
private ApiConfig apiConfigMock;
@Mock
private Configuration configMock;
@Mock
JsonObject jsonobject;


@Before
public void setup() {
    initMocks(this);
    when(configMock.getAppConfiguration()).thenReturn(jsonobject);
    when(jsonobject.getString(anyString())).thenReturn("test");
    when(salesForceDao.getForceAPI()).thenReturn(forceApiMock);
    when(new ApiConfig()).thenReturn(apiConfigMock);
    when(new ForceApi(apiConfigMock)).thenReturn(forceApiMock);
}

可能這是一個較晚的答復,但我相信它對我們中某些程序員仍然有用。

免責聲明:我從未使用過PowerMockito,但是我已經使用過很多PowerMock。關於troig的建議:PowerMock驅動的單元測試假設您將使用專用的運行器運行:

@RunWith(PowerMockRunner.class)

在這種情況下,這與問題中所述的@RunWith(BlockJUnit4ClassRunner.class)沖突,因此RunWith的“插槽”已被占用。

通過將最新版本的Power Mock作為JUnit的規則運行(我假設您正在運行JUnit),仍然可以解決這一特定問題。您可以在此處找到執行此操作的示例,但最重要的是,這是Power Mock的已知問題之一。

從根本上來說,還有其他一些問題使我得出結論,應該避免使用Power Mock,並且不應該在新項目中使用它(以及Power Mockito):

  • 帶有電源模擬的單元測試速度較慢(如果可以使用它重寫,則比EasyMock慢得多)

  • Power Mock有時會檢測與Jacoco代碼覆蓋率之類的工具不兼容的字節碼,因此聲納無法涵蓋使用Power Mock測試的類單元,或者至少是錯誤的

  • 負責在Maven中運行測試的Surefire插件具有並行運行多個單元測試的功能。 有時用權力嘲弄是不可能的。

  • 甚至IntelliJ有時也無法運行包含電源模擬測試的訴訟。

但是最重​​要的是,當您不得不使用諸如Power Mock之類的工具時,可能(並且應該)將代碼重構為更加清晰和易於理解。 關於您的特定問題:

您的類違反了編碼原則,該原則說該類不應照顧自己的依賴性。 在這里,DAO實際上是“構造”並配置另一個(外部)服務以供以后使用。

我建議您觀看Misko Hevery 關於干凈代碼的精彩演講,以更好地理解我的意思。

同樣,在您的示例中。 最好將ForceApi保持ForceApi依賴關系注入框架構造的依賴關系(我看到您已經在使用@Inject所以您ForceApi正確的軌道上)

看一下這個實現:

public abstract class AbstractDao {

  @Inject // this one is constructed and injected by your favorite DI framework in real use cases
  private ForceApi forceApi;

  public void doSomething() {
       // do your dao stuff here
       forceApi.callSomeAPIMethod();
       // do your dao stuff here
  }    
}

現在,對於單元測試,您實際上不再需要電源模擬。 根據情況,足以使用一個簡單的Mock甚至Stub。 您所需要做的就是提供一個構造函數,該構造函數將使用ForceApi類型的參數或一個setter(您可以考慮將其打包為私有,這樣任何人都無法在測試之外調用它)。

我沒有從您的問題中得到足夠的信息,但是我提供的設計可能會消除為DAO創建Abstract類的需要,這在某些情況下也可能會有所幫助,因為繼承有時可能會很繁重維持的“義務”(至少要考慮一下)。 也許在這種情況下,僅完成繼承以支持此getForceAPI行為。 在這種情況下,隨着項目的發展,可能會因為其方便性而將某些方法添加到此AbstractDAO中,但是此時這些方法將“透明地”添加到所有DAO的整個層次結構中。 這種構造變得脆弱,因為如果至少一種方法更改其實現,則DAO的整個層次結構可能會失敗。

希望這可以幫助

暫無
暫無

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

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