繁体   English   中英

使用mockito操纵参数的存根方法

[英]stubbing methods that manipulates parameters with mockito

我有以下情况:

class Worker {  
  public Integer somework() {  
      Integer k=0;  
      Helper h= new Helper();  
      h.change(k);  
      return k;  
    }
}

class Helper {
  public void change(Integer k) {
    //k = Some calcs
  }
}

我正在为Worker制作unitests,显然我想要模仿Helper类,这样他的change方法总是将1放入k

我的实际情况比较复杂,但这段代码代表了问题。 感谢帮助。

我有一个定义如下的方法:

class Template{
   public void process(Object rootMap, StringWriter out){
 .......   
  }
 }

我将向您展示如何更改/修改“out”(StringWriter)引用。

private final Template mocktTemplate = mock(Template.class);
doAnswer(new Answer<StringWriter>() {

            public StringWriter answer(InvocationOnMock invocation)
                    throws Throwable {
                Object[] args = invocation.getArguments();
                if (args[1] instanceof StringWriter) {
                    StringWriter stringWriter = (StringWriter) args[1];
                    stringWriter.write("Email message");
                }
                return null;
            }
        }).when(this.mocktTemplate).process(anyObject(),any(StringWriter.class));

现在,当您确实进行实际调用时:

msgBodyTemplate.process(model, msgBodyWriter);

msgBodyWriter中Stringbuffer ref的值为“Email message”; 不论它早期的价值。

我认为doAnswer是处理void方法的最佳方法,其中方法操纵给定的参数。

doAnswer(new Answer() {
  public Object answer(InvocationOnMock invocation) {
      Object[] args = invocation.getArguments();
      Mock mock = invocation.getMock();
      return null;
  }})
.when(mock).someMethod();

基本上,在获得参数后,您可以进行任何您想要的修改。 有一篇博客文章解释了一下。

至于@JB Nizet的观点,是的,重构可测试性是件好事。 通常,重构以使代码更易于测试会导致代码更好地用于其他原因 - 分离关注点等等。 这并不总是可行的。 假设它不是你的代码,或者你有其他要求让它不管它(因为很多其他类依赖于它的方式)或者其他什么。

如果我明白你需要做什么,我想你可以用间谍来做:

Worker workerUnderTest = new Worker();
Worker spiedWorkerUT = spy(workerUnderTest);
Helper mockHelper = mock(Helper.class);
when(spiedWorkerUT.createHelper()).thenReturn(mockHelper);
Integer actual = spiedWorkerUT.someWork();
verify(mockHelper).change(0);

然后使用spiedWorkerUT而不是workerUnderTest来运行测试。

并不总是可以避免实例化你想要模拟的东西。 为此,有PowerMock

Helper mockHelper = mock(Helper.class);
whenNew(Helper.class).withNoArguments().thenReturn(mockHelper);

我会更改方法签名,并将Helper实例作为参数。 调用者将创建帮助程序并将其传递给somework方法。 测试将通过模拟助手。

如果这是不可能的,至少调用一个受保护的工厂方法来创建帮助器,并在测试somework方法时模拟这个工厂方法,以使它返回一个模拟助手:

class Worker {  
    public Integer somework(){  
        Integer k=0;  
        Helper h= createHelper();  
        h.change(k);  
        return k;  
    }

    // this method may be mocked when testing somework, to return a mock helper.
    protected Helper createHelper() {
        return new Helper();
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM