mockito:通过反射调用参数的模拟方法

时间:2014-11-24 16:43:43

标签: java spring unit-testing mockito

我正在使用mockito并使用java6和spring进行开发。

我正在为一些开发人员开发测试API,我提出了一些模拟对象和方法的方法(它是遗留代码......)。 现在,我想用mockito替换所有这些东西,但我总是提出一个测试API。所以,我使用mockito开发了一些方法。

我有一个带有两个参数(String)的旧方法。第一个参数是模拟服务id及其带参数的方法。第二个参数是返回的Object。 示例:

mockReturnObject("myServiceId.myMethod(String, Integer)", myReturnedObject);

现在,我想使用mock,when和thenReturn mockito方法,我不知道如何...... 也许有反思但是"当"方法它是不可能的,因为mockito需要有效的方法。 我怎样才能做到这一点 ?感谢。

1 个答案:

答案 0 :(得分:4)

这是一个坏主意:你正在尝试重新实现Mockito已经提供的一些系统,同时失去了Mockito提供的许多功能。但是,有一种方法可以使这项工作有些困难。关键是要编写custom Answer,将其设为模拟的default answer,然后使用InvocationOnMock比较对象,方法名称和方法参数类型。

public class ReflectiveMockAnswer implements Answer<Object> {
  @Override public Object answer(InvocationOnMock invocation) {
    // Assume you've successfully parsed each String into a StubbedResponse, with
    // Object target, String method, String[] argTypes, and Object returnValue.
    // A Set would beat a for-loop here, should you need to optimize.
    for (StubbedResponse stubbedResponse : allStubbedResponses) {
      if (stubbedResponse.target == invocation.getMock()
          && stubbedResponse.method.equals(invocation.getMethod().getName())
          && stringArraysEqual(stubbedResponse.argTypes,
              typeNamesFrom(invocation.getMethod().getParameterTypes())) {
        return stubbedResponse.returnValue;
      }
    }
    throw new RuntimeException("Unstubbed method called.");
  }
}

// Later...
Object yourMockObject = Mockito.mock(classToMock, new ReflectiveMockAnswer());

此时,您已在Mockito的完整版本中实现了基于的Mockito 的简化版本。你还需要:

  • 将字符串解析为StubbedResponse,可能使用正则表达式
  • 按名称
  • 标识被测bean中的字段
  • 在测试中的bean有机会与之交互之前,用上面创建的相应类的模拟替换该字段

...并承认此解决方案无法处理:

  • 验证
  • 任何类型的参数匹配,包括基本的“等于”匹配
  • 参数类型中的名称冲突(com.foo.SomeClass vs com.bar.SomeClass)
  • 重复通话(thenReturn(1, 2, 3).thenThrow(new RuntimeException())

...而无法处理:

  • 代码搜索工具:您只能通过搜索字符串来判断哪些方法是模拟的,而不是像Eclipse中的“查找引用”这样的工具,就像Mockito可以
  • 一样
  • 编译时检查和自动重构工具:如果字段名称,方法名称或参数发生变化,您的测试将在运行时中断; Mockito没有那个问题
  • 最终方法:Mockito不能,所以你不能

除非这是一个“稻草人”或非常临时的解决方案,否则我强烈建议将Mockito直接引入您的测试用例,一次一个测试。