2014-04-29 30 views
1

我試圖嘲笑這種方法,但我不知道如何構造這個... 我使用Mockito和jUnit。如何測試和模擬遞歸方法?

有沒有辦法以簡單的方式做到這一點?

非常感謝。


public Object getColumnValue(ReportRow row, String columnId, Vector errors) 
{ 

     if (HSBC_PAYREC.equals(columnId)) { 
      String s = (String) getColumnValue(row, "Pay/Rcv", errors); 
      if (s != null) { 
       if (s.equals("Pay")) { 
        return "Receive"; 
       } 
      } 
      return ""; 
     } 
} 
+1

這裏有問題嗎? –

+0

看看標題。 – alzaimar

回答

2

因爲你測試被測系統,它並沒有真正有史以來意義的模擬被測系統。我認爲可以公平地說,這包括嘲諷正在測試的系統的遞歸調用。 (除了在哲學上很奇怪,你可能很難確保你從測試中調用unmocked版本,同時確保unmocked版本在它試圖調用自己時調用模擬版本。)你最好的選擇是重構您的測試,以便遞歸行爲是您的預期行爲的一部分。

這就是說,雖然它確實使代碼難以遵循,但您確實有兩種選擇。其中涉及到的部分模擬:

public Object getColumnValue(ReportRow row, String columnId, Vector errors) { 
    if (HSBC_PAYREC.equals(columnId)) { 
    String s = (String) getColumnValueRecursively(row, "Pay/Rcv", errors); 
    if (s != null) { 
     if (s.equals("Pay")) { 
     return "Receive"; 
     } 
     if (s.equals("Receive")) { 
     return "Pay"; 
     } 
     return ""; 
    } 
    } 
} 

/** For testing. */ 
Object getColumnValueRecursively(ReportRow row, String columnId, Vector errors) { 
    return getColumnValue(row, columnId, errors); 
} 

而且在測試:

@Test public void yourTest() { 
    SystemUnderTest yourSystemUnderTest = Mockito.spy(new SystemUnderTest()); 
    doReturn(yourMockedValue).when(yourSystemUnderTest).getColumnValueRecursively(
     /* your recursive base case */); 
    // ... 
} 

從技術上講,我想你可以做,沒有基於參數創建間接遞歸,但此時你交換行爲和這使得難以確保您的測試是有效的。您的其他選項同樣棘手:

SystemUnderTest recursiveInstance = this; // replace with a mock within test 

public Object getColumnValue(ReportRow row, String columnId, Vector errors) { 
    if (HSBC_PAYREC.equals(columnId)) { 
    String s = (String) recursiveInstance.getColumnValue(row, "Pay/Rcv", errors); 
    if (s != null) { 
     if (s.equals("Pay")) { 
     return "Receive"; 
     } 
     if (s.equals("Receive")) { 
     return "Pay"; 
     } 
     return ""; 
    } 
    } 
} 
0

爲了嘲笑遞歸調用,您可以使用間接遞歸,就像這樣:

private Object indirectGetColumnValue(ReportRow row, String columnId, Vector errors) { 
    return getColumnValue(row, "Pay/Rcv", errors); 
} 

public Object getColumnValue(ReportRow row, String columnId, Vector errors) { 

if (HSBC_PAYREC.equals(columnId)) { 
    String s = (String) indirectGetColumnValue(row, "Pay/Rcv", errors); 
    if (s != null) { 
     if (s.equals("Pay")) { 
      return "Receive"; 
     } 
     if (s.equals("Receive")) { 
      return "Pay"; 
     } 
    } 
    return ""; 
    } 
} 

然後你可以嘲笑indirectGetColumnValue方法。我並不是說這是首選的方法,因爲通過引入這個間接遞歸調用使得代碼不易讀。但是,這是測試它的一種方法。

+0

謝謝你,這是一個遺留代碼,我不能改變任何一行...... – HenriqueAdriano