首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Mockito的局限性

Mockito的局限性
EN

Stack Overflow用户
提问于 2016-08-11 14:44:39
回答 2查看 3.2K关注 0票数 0

我知道Mockito不支持模拟局部变量、静态方法和私有方法。有什么办法可以绕过它吗。

与私有方法一样,将方法从私有方法更改为私有方法也可以,或者我们可以将其更改为受保护的接口,以便编写测试脚本。对于静态方法和局部变量,我们有类似的东西吗?

https://github.com/mockito/mockito/wiki/FAQ说Mockito的局限性。如果它有任何其他的限制,以及如何克服它们,我指的是重构,是否有任何Mockito大师允许我。谢谢。

EN

回答 2

Stack Overflow用户

发布于 2016-08-11 18:40:05

为了帮助理解Mockito的局限性,重要的是要了解Mockito为您做了什么:Mockito为您传入的类创建了一个动态的(基于代理的)子类。这意味着,就像您自己编写的子类一样,您将无法访问或控制私有字段和方法、静态方法和局部变量。没有解决办法。

您在注释中提到了PowerMock,它通过重写要模拟的类的字节码或使用要模拟的类的类来解决Mockito的一些限制。这允许PowerMock拦截无法通过多态性覆盖的调用,特别是privatestaticfinal字段。您也无法访问局部变量。

你最好的选择是重组你的类或方法,这样它就能给你想要的控制。一般来说,您应该问“如果我创建了自己的子类,我是否能够这样做”,这个答案将有助于确定Mockito是否可以为您自动执行。

(请注意,下面我提到了“为模拟而设计的”,但您真正要做的是为您的依赖项的替代实现设计;模拟只是其中的一个例子,以及各种其他测试双倍,比如假的或内存中的实现。请记住,并不是所有的东西都需要被模拟或替换才能保持单元测试;只需确保测试中的依赖关系是快速的、确定性的和良好的测试。相反,对于缓慢、不确定、测试不佳或尚未编写的组件,用假或模拟替代实现可能会提高测试质量和覆盖率。)

代码语言:javascript
复制
public class NotDesignedForMocking {
  public int yourMethod() {
    Calculator calculator = new Calculator();  // impossible to mock!
    return calculator.calculate();
  }
}

一种技术是将依赖项作为方法参数传递。

代码语言:javascript
复制
public class DesignedForMockingViaMethodLevelDependencyInjection {
  public int yourMethod() {
    return yourMethod(new Calculator());
  }

  // Call this from tests instead; you can pass in a mock.
  int yourMethod(Calculator calculator) {
    return calculator.calculate();
  }
}

另一种方法是切换到完全依赖注入:

代码语言:javascript
复制
public class DesignedForMockingViaFullDependencyInjection {
  private final Calculator calculator;

  public DesignedForMockingViaFullDependencyInjection() {
    this(new Calculator());
  }

  // Create objects in your test with this, so you can pass in a mock Calculator.
  DesignedForMockingViaFullDependencyInjection(Calculator calculator) {
    this.calculator = calculator;
  }

  int yourMethod() {
    return calculator.calculate();
  }
}

最后,您可以创建一个可覆盖的工厂方法,它引入了Mockito在基于子类的重写中所需的多态性。

代码语言:javascript
复制
public class DesignedForMockingWithOverridableFactoryMethod {
  public int yourMethod() {
    Calculator calculator = createCalculator();
    return calculator.calculate();
  }

  // Create an anonymous override in your class, or use a Mockito spy to intercept
  // and override the behavior.
  protected Calculator createCalculator() {
    return new Calculator();
  }
}

另见:当我们不能将模拟对象传递给类的实例时,如何使用Mockito

票数 1
EN

Stack Overflow用户

发布于 2016-08-11 19:30:11

避免Mockito限制的最佳方法是不要坚持编写孤立的单元测试。

与某些人所认为的相反,单元测试不需要与被测试单元的依赖关系隔离运行。正如马丁·福勒 (以及TDD的“父亲”Kent所实践的那样),单元测试可以是“社会化的”(没有对依赖关系的嘲弄)或“孤立的”(带有模拟的依赖)。

因此,避免那些嘲讽工具限制的方法之一就是根本不依赖它们。您可以通过编写“社会化”单元测试来实现这一点,或者(像我一样)一路编写集成测试。

前面提到的另一个“解决方案”是重构正在测试的代码,以绕过模拟限制,或者“设计用于嘲弄”(正如Jeff所说)。我希望大多数开发人员认识到这是一个糟糕的解决方案,因为它通常需要在SUT中增加额外的复杂性,以弥补特定的模拟库中的任意限制。考虑增加private方法的可访问性的情况,这样就可以直接测试或模拟它。那么,如果您认为这是可以接受的,那么您真的关心代码质量吗?如果你不在乎,那你为什么还要费心于自动化的开发人员测试呢?

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38899562

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档