【问题标题】:Using Mockito, how can I mock a return value of an instance method without having an instance of that class?使用 Mockito,如何在没有该类的实例的情况下模拟实例方法的返回值?
【发布时间】:2016-03-19 01:16:03
【问题描述】:

我有一个名为MyClass 的课程。我在那个类中有一个方法,public int getSpacing()

我正在测试来自不同类的方法。 public static ArrayList<SpecialObject> getSpecialObjects().

getSpecialObjects()MyClass 的实例上调用 getSpacing()。当我使用 Mockito 运行测试时,我希望此方法始终返回 0。我怎样才能做到这一点?我发现的所有示例都需要对象的特定实例才能模拟方法。

这是我知道该怎么做的。

MyClass myInstance = new MyClass();        
Mockito.when(myInstance.getSpacing()).thenReturn(0);

但是,我想为MyClass 的所有实例覆盖getSpacing() 的行为,因为这些实例是在getSpecialObjects() 中动态创建的。我该怎么做?

这就是我想说但不知道怎么说的。

Mockito.when((Any instance of MyClass).getSpacing()).thenReturn(0);

【问题讨论】:

  • myInstance 需要初始化。可以显示你的代码吗?
  • @JaredBurrows 我修复了这个例子。这是我的代码的简化版本。我的问题是我无权访问该实例,我想覆盖所有实例的行为。
  • 我认为这是不可能的,你有没有机会在你需要的地方注入一个模拟实例?

标签: java android unit-testing junit mockito


【解决方案1】:

你不能像你描述的那样纯粹在 Mockito 中做到这一点。 Mockito 并不控制 MyClass 类型的所有对象,而是可以很容易地创建和实例化它可以控制的代理子类。这就是 Mockito 依赖于非最终类和方法的原因,也是您无法使用 Mockito 影响所有实例行为的原因。

另请参阅: How to use Mockito when we cannot pass a mock object to an instance of a class

一种解决方法是切换库:As Slava describes,您可以使用 PowerMock,它有一个可修改字节码的自定义类加载器,其中包括替换对 new MyClass() 构造函数的调用,以便它们可以返回您的模拟。

作为替代方案,您可以重组类以使其更易于测试。您可以完全构建依赖注入的类并注入Provider<MyClass>,但有一个更本地化的解决方案,具有大部分好处:

public class ClassThatConsumesMyClass {
  /** Visible for testing. Override to customize MyClass instances. */
  MyClass createMyClass() {
    return new MyClass();
  }

  public ReturnValue getSpecialObjects(int n) {
    for (int i = 0; i < n; i++) {
      // Instead of calling "new MyClass()", call your method.
      MyClass myClassInstance = createMyClass();
      // ...
    }
    // ...
  }
}

public class TestForClassThatConsumesMyClass {
  ClassThatConsumesMyClass consumer;

  @Before public void createMyClass() {
    consumer = new ClassThatConsumesMyClass() {
      @Override MyClass createMyClass() {
        MyClass myInstance = Mockito.mock(MyClass.class);
        Mockito.when(myInstance.getSpacing()).thenReturn(0);
        return myInstance;
      }
    }
  }

  // Test as usual, now that you've mocked every newly-created
  // instance of MyClass in your consumer.
}

【讨论】:

    【解决方案2】:

    您可以像这样使用 powermock 模拟 MyClass 构造函数:

    MyClass myClassSpy = spy(new MyClass());
    whenNew(MyClass.class).withAnyArguments().thenReturn(myclassSpy);
    

    然后,您可以使用间谍的常规覆盖从该方法返回您喜欢的任何内容。别忘了PrepareForTestMyClass

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-17
      • 1970-01-01
      • 2021-01-07
      • 1970-01-01
      • 2014-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多