你能让 mockito (1.10.17) 在接口中使用默认方法吗?

2022-09-01 17:30:09

我是mockito的忠实粉丝,不幸的是,对于我的一个使用Java 8的项目,它在我身上失败了......

场景:

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;
        }
    }
}

不幸的是,测试失败并返回 0。foo.bar()

当我取消注释该行时,我得到一个堆栈跟踪...when()

java.lang.NoSuchMethodError: java.lang.Object.bar()I
    at com.github.fge.lambdas.MockTest.testDefaultMethodsWithMocks(MockTest.java:18)

这是maven上可用的最新稳定版本;谷歌搜索并没有告诉我很多关于mojito在Java 8中这个新功能方面的地位......

你能让它以其他方式工作,而不是实现接口和它们(这有效)吗?spy()


答案 1

对于 mockito 2.x支持 JDK 8 默认方法。

使用mojito 1.x是不可能的,


旧答案

不幸的是,这还是不可能的(mockito 1.10.19),从github'page上README.md

JDK8 状态

Mockito应该可以很好地与JDK8一起使用,如果你远离默认方法(又名防御者方法)。Lambda 的使用可能同样适用于答案。我们目前不确定JDK8的每个功能,比如序列化使用lambda的模拟。欢迎错误报告和拉取请求(贡献指南)。

编辑1防御方法默认方法是同一事物的不同名称。

我希望有一个模拟器替代品,可以正确处理java 8操作码,例如某些操作码在Java 8中具有不同的语义。

编辑2:更新了模拟自述文件,并相应地引用了这句话


答案 2

我刚刚尝试了Mockito 2.0.38-beta,它已经可以在该版本中运行。但是必须明确告诉 Mockito 调用默认实现。

Foo foo = mock(Foo.class);
assertThat(foo.bar()).isEqualTo(0);

when(foo.bar()).thenCallRealMethod();
assertThat(foo.bar()).isEqualTo(42);

推荐