我是mockito的忠实粉丝,不幸的是对于使用Java 8的one of my projects来说,它在我身上失败了...
场景:
public final class MockTest
{
@Test
public void testDefaultMethodsWithMocks()
{
final Foo foo = mock(Foo.class);
//when(foo.bar()).thenCallRealMethod();
assertThat(foo.bar()).isEqualTo(42);
}
@FunctionalInterface
private interface Foo
{
int foo();
default int bar()
{
return 42;
}
}
}
不幸的是,测试失败,foo.bar()
返回0。
当我取消注解when()
行时,我得到一个堆栈跟踪...
java.lang.NoSuchMethodError: java.lang.Object.bar()I
at com.github.fge.lambdas.MockTest.testDefaultMethodsWithMocks(MockTest.java:18)
这是Maven上可用的最新稳定版本;在Google上搜索并没有告诉我很多关于Java 8中这个新功能的mockito状态...
除了实现接口和spy()
之外,您还能用其他方式使它工作吗?
7条答案
按热度按时间kq0g1dla1#
使用mockito 2.x,支持JDK 8默认方法。
对于mockito 1.x,这是不可能的,
"旧答案"
不幸的是,这还不可能(mockito 1.10.19),来自github'页面上的
README.md
JDK8状态
如果你不使用默认方法(也叫defender方法),Mockito在JDK8中应该可以很好地工作。Lambda的使用可能也同样适用于Answers。我们目前还不确定JDK8的每一个特性,比如序列化一个使用lambda的mock。但是欢迎错误报告和拉取请求(贡献指南)。
EDIT 1:*defender方法 * 和 *default方法 * 是同一个对象的不同名称。
我希望有一个mockmaker的替代品,它可以正确地处理java8操作码,因为在java8中某些操作码具有不同的语义。
编辑2:更新了mockito自述文件,并相应地更新了此报价
uubf1zoe2#
我刚刚试用了Mockito 2.0.38-beta,它已经可以在那个版本中工作了。但是必须明确告诉Mockito调用默认实现。
iswrvxsc3#
Mockito(在版本3上可以使用)可以使用
default
方法。下面是用JUnit 5重写的示例代码,这样它就可以工作了:调用real方法的应答在最新的Mockito中确实有效。一般来说,扩展使mock的创建更具声明性,但是
mock
方法也提供了一个重载,它支持默认应答,如上面的@Mock
注解所示:https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#mock-java.lang.Class-org.mockito.stubbing.Answer-wqlqzqxt4#
您可以通过实现接口(在Mockito 1.10.19中测试)来解决这个限制:
mv1qrgav5#
我刚刚在Mockito(org.mockito:mockito-core:1.10.19)上遇到了同样的问题。我无法更改Mockito版本(2.7.22版可以),因为它依赖于我们正在使用的org.springframework.boot:spring-boot-starter-test:1.4.3.RELEASE(Spring, Mockito issue)。
我找到的最简单的解决方案是在我的测试类中用一个私有抽象类实现接口,并模仿那个类(也可以与@Mihai Bojin的解决方案比较)。这样做可以让你远离“实现”接口所需的所有方法的麻烦。
我的天
ncecgwcz6#
另一种解决方案是使用
Spy
,如下所述:https://stackoverflow.com/a/54915791/36368222g32fytz7#
只是一个小小的侧记,特别是函数接口可以很容易地创建,而不需要模仿。如果你需要调用一些验证方法之后,你可以 Package 示例到一个间谍。
有时候,我们太习惯于使用这些框架,以至于很容易忘记那些显而易见的解决方案。