我知道Mockito并不支持模拟局部变量,静态方法和私有方法。有没有办法解决它。
就像私有方法从private更改方法一样,或者我们可以将其更改为受保护的接口,以便我们可以编写测试脚本。那么对于静态方法和局部变量我们有这样的东西。
https://github.com/mockito/mockito/wiki/FAQ说Mockito的局限性。任何Mockito大师都可以让我,如果它有任何其他限制,如何克服它们我的意思是重构。谢谢。
答案 0 :(得分:0)
为了帮助理解Mockito的限制,了解Mockito为您做的事情非常重要: Mockito创建了您传入的类的动态(基于代理)子类。这意味着,就像您自己编写的子类一样,您无法访问或控制私有字段和方法,静态方法和局部变量。没有解决方法。
你在评论中提到了PowerMock,它通过重写你想要模拟的类的字节码,或者使用你想要模拟的类的类来解决一些Mockito限制。这允许PowerMock拦截您无法通过多态性覆盖的呼叫,尤其是private
,static
和final
字段。您也无法访问本地变量。
相反,您最好的选择是重组您的课程或方法,以便它确实为您提供所需的控制权。一般来说,如果我创建了自己的子类",我应该问"我能做到这一点吗?这个答案将有助于确定Mockito是否可以为你自动化。
(请注意,我在下面提到"专为嘲笑",但你真正在做的是设计依赖项的替代实现;模拟只是其中的一个例子,以及各种其他测试双打,如假或内存实现。请记住,并非所有内容都需要被模拟或替换为您的测试以保持单元测试;只需确保您的依赖项在测试中相反,对于缓慢的,不确定的,测试不良的或未写的组件,用假或模拟替换实现可以提高测试质量和覆盖范围。)
public class NotDesignedForMocking {
public int yourMethod() {
Calculator calculator = new Calculator(); // impossible to mock!
return calculator.calculate();
}
}
一种技巧是将您的依赖项作为方法参数传递。
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();
}
}
另一种方法是切换到完全依赖注入:
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基于子类的覆盖所需的多态性。
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();
}
}
另请参阅:How to use Mockito when we cannot pass a mock object to an instance of a class
答案 1 :(得分:-1)
避免Mockito限制的最佳方法是不要坚持编写隔离单元测试。
与某些人的想法相反,单元测试不需要与被测单元的依赖关系分开运行。正如described by Martin Fowler(和Kent Beck所做的那样,"父亲" TDD),单元测试可以是'社交'和#34; (没有嘲笑依赖)或"孤独" (使用模拟依赖项)。
因此,避免这些模拟工具限制的一种方法是简单地不依赖它们。您可以通过撰写" sociable"单元测试,或者(像我一样)全力以赴地编写集成测试。
另一个"解决方案"提到的是重构被测试的代码以解决模拟限制,或者设计用于模拟" (正如杰夫鲍曼所说)。
我希望大多数开发人员意识到这是一个糟糕的解决方案,因为它通常需要为SUT增加额外的复杂性,只是为了弥补特定模拟库中的任意限制。
考虑增加private
方法的可访问性的情况,以便您可以直接测试它或模拟它。好吧,如果你觉得可以接受,你真的关心代码质量吗?如果您不在乎,那么为什么还要为自动开发人员测试而烦恼呢?