我还有最后一节课,大概是这样的:
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通常对我来说就足够了。事实上,以这种方式限制有时也会迫使我进行重构。
为那些在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