2017-08-02 463 views
-2

我的問題是如何使用Mockito的doAnswer來調用原始方法和我自己的測試參數。使事情複雜化,其中一個參數不是原始的。這是一個自定義類。如何使用具有多個參數的Mockito模擬setter方法

考慮以下幾點:

public class EnvironmentQualityStatus { 
    public int environmentQuality = EnvironmentQualityStatus.NA; 
    public long cht = -1; 
    public int environmentSubType = -1; 
    public String engineer=""; 
    public int engineerType = -1; 
    public long timeStamp = 0; 
    public static final String version = "tpv1"; 

    EnvironmentQualityStatus(){} 

    EnvironmentQualityStatus(int environmentQuality, long cht, int environmentSubType, String engineer, int engineerType) { 
     this.environmentQuality = environmentQuality; 
     this.cht = cht; 
     this.environmentSubType = environmentSubType; 
     this.engineer = engineer; 
     this.engineerType = engineerType; 
     timeStamp = System.currentTimeMillis(); 
    } 

    @Override 
    public String toString() { 
     StringBuilder sb = new StringBuilder(); 
     sb.append("ts: "); 
     sb.append(timeStamp); 
     sb.append(", quality: "); 
     sb.append(EnvironmentQualityStatus.valueOf(environmentQuality)); 
     sb.append(", cht: "); 
     sb.append(cht); 
     sb.append(", type: "); 
     if (engineerType == Engineers.TYPE_CIVIL) { 
      sb.append(「civil」); 
     } else if (engineerType == Engineers.TYPE_INDUSTRIAL) { 
      sb.append(「industrial」); 
      if (!TextUtils.isEmpty(engineer)) { 
       sb.append(", Engineer: "); 
       sb.append(engineer); 
      } 
     } else { 
      sb.append("n/a"); 
     } 
     return sb.toString(); 
    } 
} 

考慮到使用上面的代碼設置一些東西在一類。這是我想用Mockito嘲笑的這個電話(以及其他人)。

public class EnvironmentQuality { 
... 
public void updateEnvironmentQuality(EnvironmentQualityStatus eqStatus , 
             int environmentQuality ,int cht , String engineer, boolean notify){ 
     //set some stuff.... 
    } 
} 

我知道使用Mockito的doAnswer是正確的方法。我只是無法弄清楚如何連接最後一部分,我用自己的操作來調用所調用的值,以便在測試運行時使用它們的程序獲取我的值。我已經閱讀了Mockito文檔以及圍繞這個主題的幾篇SO帖子,但它仍然不清楚。

EnvironmentQuality environmentQuality = spy((EnvironmentQuality)EnvironmentQuality.getInstance(context)); 

    spy(environmentQuality).updateNetworkQuality(Mockito.any(com.something.internal.EnvironmentQualityStatus.class), anyInt(), anyInt(), anyString(), anyBoolean()); 
    doAnswer(new Answer<Void>() { 
     @Override 
     public Void answer(InvocationOnMock invocation) throws Throwable { 

      //This is an example of how to spy the parameters that were passed. 
      EnvironmentQualityStatus status = (EnvironmentQualityStatus)invocation.getArguments()[0]; 

      int environmentQuality = (int)invocation.getArguments()[1]; 
      int cht = (int)invocation.getArguments()[2]; 
      String engineer = (String)invocation.getArguments()[3]; 
      boolean notify = (boolean)invocation.getArguments()[4]; 

      //But how to customize the parameters so that every time updateEnvironmentQuality(...) is called, a test can customize the params and dynamically influence the values. 
      return null; 
     } 
    }).when(environmentQuality).updateEnvironmentQuality(Mockito.any(com.something.internal.EnvironmentQualityStatus.class), anyInt(), anyInt(), anyString(), anyBoolean()); 
+1

您只能在doAnswer內更新EnvironmentQualityStatus參數,因爲其餘部分是不可變的。 –

+1

爲什麼是-1?我認爲這個問題和你的答案可以向其他人澄清。 –

+1

你的問題不清楚。你是否說你想要調用真實版本的stubbed方法,但是修改了參數的值?我不相信Mockito目前可以做到這一點,但是您可以提交功能請求。 –

回答

1

所以我假設你想調用其他值的方法。通過檢查the documentationInvocationOnMock,您可以檢查如何獲得被調用的MethodObject。所以這應該很容易修改:

@Override 
    public Void answer(InvocationOnMock invocation) throws Throwable { 
     Object callingObject = invocation.getMock(); 
     Method method = invocation.getMethod(); 
     method.invoke(callingObject, /* arguments... */); 
     return null; 
    } 
+0

我想補充一點。在你試圖代理方法的情況下(就像我正在做的那樣),我們最終會以遞歸調用的形式結束。當我們用自己的參數調用方法時,我們會再次回到Answer中。所以解決這個問題的方法是使用反射來獲取setter方法設置的成員變量。因此,結果(對我們來說)是一樣的,沒有遞歸問題。你的旅費可能會改變。 –

+0

你測試過了嗎?我不確定它會起作用。按照Method的invoke方法的Javadoc,使用動態方法查找調用它,如Java語言規範第2版第15.12.4.4節所述;特別是基於目標對象的運行時類型將發生......「_這意味着您只需在存根對象上再次調用該方法。所以你的'answer'方法會重複調用它自己,直到你的堆棧溢出。 –

相關問題