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

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做到这一点?


当前回答

为那些在Android + Kotlin上面临相同问题(Mockito + Final Class)的人节省时间。在Kotlin中,默认情况下类是final的。我在谷歌的一个Android样本中找到了一个解决方案。解决方案从这里选择:https://github.com/googlesamples/android-architecture-components/blob/master/GithubBrowserSample

创建以下注释:

/**
 * This annotation allows us to open some classes for mocking purposes while they are final in
 * release builds.
 */
@Target(AnnotationTarget.ANNOTATION_CLASS)
annotation class OpenClass

/**
 * Annotate a class with [OpenForTesting] if you want it to be extendable in debug builds.
 */
@OpenClass
@Target(AnnotationTarget.CLASS)
annotation class OpenForTesting

修改gradle文件。举个例子:https://github.com/googlesamples/android-architecture-components/blob/master/GithubBrowserSample/app/build.gradle

apply plugin: 'kotlin-allopen'

allOpen {
    // allows mocking for classes w/o directly opening them for release builds
    annotation 'com.android.example.github.testing.OpenClass'
}

现在你可以注释任何类,使其开放测试:

@OpenForTesting
class RepoRepository 

其他回答

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

我认为原则上你需要多想想。相反,你最终类使用他的接口和模拟接口。

:

 public class RainOnTrees{

   fun startRain():Observable<Boolean>{

        // some code here
   }
}

add

interface iRainOnTrees{
  public void startRain():Observable<Boolean>
}

并模拟你的界面:

 @Before
    fun setUp() {
        rainService= Mockito.mock(iRainOnTrees::class.java)

        `when`(rainService.startRain()).thenReturn(
            just(true).delay(3, TimeUnit.SECONDS)
        )

    }

如果您试图在test文件夹下运行unit-test,那么顶部的解决方案是可以的。只要跟着它添加一个扩展。

但如果你想运行与android相关的类,如context或activity,在androidtest文件夹下,答案是你。

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

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

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

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

添加到你的gradle文件:

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

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

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