我还有最后一节课,大概是这样的:

public final class RainOnTrees{

   public void startRain(){

        // some code here
   }
}

我在其他一些类中使用这个类,像这样:

public class Seasons{

   RainOnTrees rain = new RainOnTrees();

   public void findSeasonAndRain(){

        rain.startRain();

    }
}

在我的JUnit测试类Seasons.java中,我想模拟RainOnTrees类。我怎么能用Mockito做到这一点?


当前回答

使用Powermock。这个链接展示了如何做到这一点:https://github.com/jayway/powermock/wiki/MockFinal

其他回答

只有在Mockito v2中才可以模拟final/static类/方法。

添加到你的gradle文件:

testImplementation 'org.mockito:mockito-inline:2.13.0'

这是不可能与Mockito v1,从Mockito常见问题:

Mockito的局限性是什么 需要java1.5 + 不能模拟最终类 ...

我也有同样的问题。由于我试图模拟的类是一个简单的类,所以我只是创建了它的一个实例并返回该实例。

我猜,您之所以将它作为final,是因为您希望阻止其他类扩展RainOnTrees。正如Effective Java所建议的(第15项),有另一种方法来保持类接近于扩展而不使其成为final:

删除最后一个关键字; 将其构造函数设为private。没有类能够扩展它,因为它不能调用超构造函数; 创建一个静态工厂方法来实例化你的类。 //这里没有final关键字。 公共类RainOnTrees { 公共静态RainOnTrees newInstance() { 返回新的RainOnTrees(); } 私有RainOnTrees() { //私有构造函数。 } 公共无效startRain() { //这里有一些代码 } }

通过使用这种策略,您将能够使用Mockito并使用很少的样板代码保持类关闭以供扩展。

在某些情况下可能适用的另一种解决方法是创建一个由最终类实现的接口,更改代码以使用该接口而不是具体类,然后模拟该接口。这样可以将契约(接口)与实现(最终类)分离。当然,如果您真正想要的是绑定到最终的类,这将不适用。

由RC和Luigi R. Viggiano共同提供的解决方案可能是最好的主意。

尽管Mockito在设计上不能模拟final类,但是委托方法是可能的。这有它的优点:

如果API一开始就打算将类改为非final类(final类有其好处),那么不必强制将类改为非final类。 您正在测试API周围装饰的可能性。

在您的测试用例中,您故意将调用转发到被测试的系统。因此,通过设计,你的装饰什么都不做。

因此,测试还可以证明用户只能修饰API,而不能扩展API。

从更主观的角度来看: 我更喜欢将框架保持在最低限度,这就是为什么JUnit和Mockito通常对我来说就足够了。事实上,以这种方式限制有时也会迫使我进行重构。