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

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


当前回答

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

如果使用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

其他回答

如果你正在使用Mockito2,这可以做到,新的孵化功能支持模拟最终类和方法。

需要注意的要点: 1. 创建一个名为“org.mockito.plugins”的简单文件。并将其放在名为mockito-extensions的文件夹中。这个文件夹应该在类路径上可用。 2. 上面创建的文件内容应该是一行,如下所示: mock-maker-inline

为了激活mockito扩展机制并使用此选择加入特性,需要执行上述两个步骤。

示例类如下:-

FinalClass.java

public final class FinalClass {

public final String hello(){
    System.out.println("Final class says Hello!!!");
    return "0";
}

}

Foo.java

public class Foo {

public String executeFinal(FinalClass finalClass){
    return finalClass.hello();
}

}

FooTest.java

public class FooTest {

@Test
public void testFinalClass(){
    // Instantiate the class under test.
    Foo foo = new Foo();

    // Instantiate the external dependency
    FinalClass realFinalClass = new FinalClass();

    // Create mock object for the final class. 
    FinalClass mockedFinalClass = mock(FinalClass.class);

    // Provide stub for mocked object.
    when(mockedFinalClass.hello()).thenReturn("1");

    // assert
    assertEquals("0", foo.executeFinal(realFinalClass));
    assertEquals("1", foo.executeFinal(mockedFinalClass));

}

}

希望能有所帮助。

完整的文章呈现在这里嘲笑不可嘲笑的。

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

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

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

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

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

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

对我们来说,这是因为我们从koin-test中排除了mockito-inline。一个gradle模块实际上需要这个,并且由于某些原因,它只在发布版本中失败了(IDE中的调试版本可以工作):-P

为那些在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 

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

如果使用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