but*_*ski 169 java junit mockito
我有一个最后的课,类似这样:
public final class RainOnTrees{
public void startRain(){
// some code here
}
}
Run Code Online (Sandbox Code Playgroud)
我在其他类中使用此类,如下所示:
public class Seasons{
RainOnTrees rain = new RainOnTrees();
public void findSeasonAndRain(){
rain.startRain();
}
}
Run Code Online (Sandbox Code Playgroud)
在我的JUnit测试类中,Seasons.java我想模拟这个RainOnTrees类.我怎么能和Mockito一起做这件事?
Win*_*der 170
Mockito 2现在支持最终的类和方法!
但就目前而言,这是一个"孵化"功能.它需要一些步骤来激活它,这在Mockito 2的新功能中有所描述:
最终类和方法的模拟是一种孵化,选择加入的功能.它使用Java代理程序检测和子类化的组合,以实现这些类型的可模拟性.由于这与我们当前的机制不同,并且这个机制具有不同的限制,并且由于我们希望收集经验和用户反馈,因此必须明确激活此功能以使其可用; 它可以通过mockito扩展机制通过创建
src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker包含单行的文件来完成:Run Code Online (Sandbox Code Playgroud)mock-maker-inline创建此文件后,Mockito将自动使用此新引擎,并且可以执行以下操作:
Run Code Online (Sandbox Code Playgroud)final class FinalClass { final String finalMethod() { return "something"; } } FinalClass concrete = new FinalClass(); FinalClass mock = mock(FinalClass.class); given(mock.finalMethod()).willReturn("not anymore"); assertThat(mock.finalMethod()).isNotEqualTo(concrete.finalMethod());在随后的里程碑中,团队将采用以编程方式使用此功能.我们将为所有不可挽救的场景确定并提供支持.请继续关注,请告诉我们您对此功能的看法!
小智 116
使用Mockito常见问题解答中的 Mockito v1是不可能的:
Mockito有什么限制
需要java 1.5+
不能模拟最后的课程
...
Lui*_*ano 41
你不能用Mockito嘲笑最后一堂课,因为你不能自己做.
我所做的是创建一个非final类来包装最终类并用作委托.这方面的一个例子是TwitterFactory类,这是我的可模拟类:
public class TwitterFactory {
private final twitter4j.TwitterFactory factory;
public TwitterFactory() {
factory = new twitter4j.TwitterFactory();
}
public Twitter getInstance(User user) {
return factory.getInstance(accessToken(user));
}
private AccessToken accessToken(User user) {
return new AccessToken(user.getAccessToken(), user.getAccessTokenSecret());
}
public Twitter getInstance() {
return factory.getInstance();
}
}
Run Code Online (Sandbox Code Playgroud)
缺点是有很多样板代码; 优点是您可以添加一些可能与您的应用程序业务相关的方法(例如,在上述情况下,用户而不是accessToken的getInstance).
在你的情况下,我将创建一个RainOnTrees委托给最终类的非final类.或者,如果你能使它成为非最终的,那就更好了.
Ben*_*nyP 27
将其添加到您的gradle文件中:
testImplementation 'org.mockito:mockito-inline:2.13.0'
Run Code Online (Sandbox Code Playgroud)
这是使mockito与最终类一起工作的配置
Gáb*_*ták 24
使用Powermock.此链接显示,如何操作:https://github.com/jayway/powermock/wiki/MockFinal
Mic*_*ang 15
只是为了跟进.请将此行添加到您的gradle文件中:
testCompile group: 'org.mockito', name: 'mockito-inline', version: '2.8.9'
Run Code Online (Sandbox Code Playgroud)
我尝试了各种版本的mockito-core和mockito-all.它们都不起作用.
Sat*_*tar 14
在 Mockito 3 及更多版本中,我遇到了同样的问题并从此链接修复了它
在 Mockito 可以用于模拟 final 类和方法之前,需要对其进行 > 配置。
我们需要在项目的 src/test/resources/mockito-extensions 目录下添加一个文本文件,名为 org.mockito.plugins.MockMaker 并添加一行文本:
Run Code Online (Sandbox Code Playgroud)mock-maker-inlineMockito 在加载时检查扩展目录中的配置文件。该文件允许模拟最终方法和类。
Flá*_*ria 11
我猜你是final因为你想阻止其他类扩展RainOnTrees.正如Effective Java建议的那样(第15项),还有另一种方法可以让一个类关闭扩展而不进行扩展final:
删除final关键字;
制作它的构造函数private.没有类可以扩展它,因为它无法调用super构造函数;
创建一个静态工厂方法来实例化您的类.
// No more final keyword here.
public class RainOnTrees {
public static RainOnTrees newInstance() {
return new RainOnTrees();
}
private RainOnTrees() {
// Private constructor.
}
public void startRain() {
// some code here
}
}
Run Code Online (Sandbox Code Playgroud)通过使用此策略,您将能够使用Mockito并使用很少的样板代码关闭扩展类.
我有同样的问题.由于我试图模拟的类是一个简单的类,我只是创建了它的一个实例并返回它.
尝试一下:
Mockito.mock(SomeMockableType.class,AdditionalAnswers.delegatesTo(someInstanceThatIsNotMockableOrSpyable));
Run Code Online (Sandbox Code Playgroud)
它对我有用."SomeMockableType.class"是您想要模拟或间谍的父类,而someInstanceThatIsNotMockableOrSpyable是您要模拟或间谍的实际类.
有关详细信息,请查看此处
为在 Android + Kotlin 上遇到相同问题(Mockito + Final Class)的人节省时间。在 Kotlin 中,类默认是 final 的。我在一个带有架构组件的 Google 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
Run Code Online (Sandbox Code Playgroud)
修改你的 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'
}
Run Code Online (Sandbox Code Playgroud)
现在您可以注释任何类以使其开放进行测试:
@OpenForTesting
class RepoRepository
Run Code Online (Sandbox Code Playgroud)
在某些情况下可能适用的另一种解决方法是,创建由该最终类实现的接口,更改代码以使用该接口而不是具体的类,然后模拟该接口。这使您可以将合同(接口)与实现(最终类)分开。当然,如果您真正想要绑定到最终类,则这将不适用。
实际上有一种方法,我用它来进行间谍活动。只有满足两个先决条件,它才会对你有用:
请回忆《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(); }
}
Run Code Online (Sandbox Code Playgroud)
现在你不仅可以模拟你的最后一堂课,还可以监视它:
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();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
211361 次 |
| 最近记录: |