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

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


当前回答

请看JMockit。它有大量的文档和示例。这里你有一个解决你的问题的例子(为了简化,我添加了构造函数到Seasons注入模拟RainOnTrees实例):

package jmockitexample;

import mockit.Mocked;
import mockit.Verifications;
import mockit.integration.junit4.JMockit;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(JMockit.class)
public class SeasonsTest {

    @Test
    public void shouldStartRain(@Mocked final RainOnTrees rain) {
        Seasons seasons = new Seasons(rain);

        seasons.findSeasonAndRain();

        new Verifications() {{
            rain.startRain();
        }};
    }

    public final class RainOnTrees {
        public void startRain() {
            // some code here
        }

    }

    public class Seasons {

        private final RainOnTrees rain;

        public Seasons(RainOnTrees rain) {
            this.rain = rain;
        }

        public void findSeasonAndRain() {
            rain.startRain();
        }

    }
}

其他回答

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

添加到你的gradle文件:

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

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

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

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

:

 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文件夹下,答案是你。

实际上有一种方法,我用来监视的。只有满足两个前提条件,它才会为你工作:

使用某种DI注入final类的实例 Final类实现了一个接口

请回顾Effective Java中的第16项。你可以创建一个包装器(不是final)并将所有调用转发给final类的实例:

public final class RainOnTrees implement IRainOnTrees {
    @Override public void startRain() { // some code here }
}

public class RainOnTreesWrapper implement IRainOnTrees {
    private IRainOnTrees delegate;
    public RainOnTreesWrapper(IRainOnTrees delegate) {this.delegate = delegate;}
    @Override public void startRain() { delegate.startRain(); }
}

现在你不仅可以模仿你的最后一个类,还可以监视它:

public class Seasons{
    RainOnTrees rain;
    public Seasons(IRainOnTrees rain) { this.rain = rain; };
    public void findSeasonAndRain(){
        rain.startRain();
   }
}

IRainOnTrees rain = spy(new RainOnTreesWrapper(new RainOnTrees()) // or mock(IRainOnTrees.class)
doNothing().when(rain).startRain();
new Seasons(rain).findSeasonAndRain();

如果你需要在Android的测试中使用Mockito(即在Android设备中运行),你不能使用Mockito -inline。有一个特殊的模拟android版本也没有解决“最终类”的问题。唯一可行的解决方案似乎是Dexmaker库。唯一的限制是它只能在Android P (Android 9, API 28)或更高版本上运行。导入方式如下:

androidTestImplementation "com.linkedin.dexmaker:dexmaker-mockito-inline:2.28.1"

注意,还有一个“dexmaker-mockito”版本,它也不适用于final类。确保您导入了“dexmaker-mockito-inline”。