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

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


当前回答

根据这个GitHub问题,mockito-android不支持mock final类。您应该使用Mockk代替它。

对于单元测试和ui测试,都可以毫无问题地使用Mockk。

其他回答

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

使用某种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();

请看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。准确地说,Mockito不能模仿/监视以下内容:

最后的课程 匿名类 原始类型

但是在我看来,使用包装器类代价很大,所以改用PowerMockito。

在构建文件中添加以下内容:

如果使用gradle: build.gradle

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

如果使用maven: pom.xml

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-inline</artifactId>
    <version>2.13.0</version>
    <scope>test</scope>
</dependency>

这是一个使mockito与final类一起工作的配置

如果您面临无法初始化内联字节伙伴模拟生成器。(Android不支持这个模拟生成器。) 将字节伙伴依赖项添加到构建中。gradle文件:

testImplementation 'net.bytebuddy:byte-buddy-agent:1.10.19'

src: https://mvnrepository.com/artifact/net.bytebuddy/byte-buddy

没有尝试final,但私有,使用反射删除修饰符工作!已经进一步检查,它不为最终工作。