2017-08-02 59 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'方法会重复调用它自己,直到你的堆栈溢出。 –

相关问题