mockito:通过反射使用参数模拟方法调用 [英] mockito : mock method call with parameters by reflection

查看:193
本文介绍了mockito:通过反射使用参数模拟方法调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm using mockito and developping with java6 and spring.

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

I'm working on a test API for some developpers and I propose a few methods for mocking objects and methods (it's a legacy code...). Now, I want to replace all this things by mockito but I always propose a test API. So, I developped some methods using mockito.

我有一个带有两个参数(字符串)的旧方法.第一个参数是模拟的服务 ID 及其带参数的方法.第二个参数是返回的对象.示例:

I have an old method with two parameters (String). A first parameter is a mocked service id and its method with parameters. And the second parameter is the returned Object. Example :

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

现在,我想用mock,when和then返回mockito方法,不知道怎么...也许使用反射但使用何时"方法是不可能的,因为 mockito 需要有效的方法.我怎样才能做到这一点 ?谢谢.

Now, I want to use mock, when and thenReturn mockito methods, and I don't see how... Perhaps with reflection but with "when" method it's impossible because mockito need the effective method. How can I do that ? thanks.

推荐答案

这是个坏主意:您试图重新实现 Mockito 已经提供的一些系统,同时失去了 Mockito 提供的许多功能.但是,有一种方法可以使这项工作发挥作用,但有一些困难.关键是要写一个 自定义答案,使其成为默认答案 用于模拟,然后使用 InvocationOnMock.

This is a bad idea: you're trying to reimplement some of the systems Mockito already provides while losing out on many of the features Mockito offers. However, there is a way to make this work, with some difficulty. The key is to write a custom Answer, make it the default answer for the mock, and then compare your object, method name, and method parameter types using 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 的简化版.您还需要:

At that point, you've implemented a simplified version of Mockito within and based on the full version of Mockito. You'll also need to:

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

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

...and acknowledge that this solution doesn't handle:

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

...并且不能处理:

  • 代码搜索工具:您只能通过搜索字符串来判断哪些方法被模拟,而不能使用诸如查找引用"之类的工具.在 Eclipse 中使用 Mockito 的方式
  • 编译时检查和自动重构工具:如果字段名称、方法名称或参数发生变化,您的测试将在运行时中断;Mockito 没有这个问题
  • 最终方法:Mockito 不能,所以你也不能

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

Unless this is a "straw man" or very temporary solution, I recommend strongly to just introduce Mockito directly into your test cases, one test at a time.

这篇关于mockito:通过反射使用参数模拟方法调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆