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

fge*_*fge 21 java mockito java-8 default-method

我是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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

java.lang.NoSuchMethodError: java.lang.Object.bar()I
    at com.github.fge.lambdas.MockTest.testDefaultMethodsWithMocks(MockTest.java:18)
Run Code Online (Sandbox Code Playgroud)

这是maven上最新的稳定版本; 谷歌搜索周围没有告诉我关于Java 8中这个新功能的模拟状态...

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

Bri*_*ice 11

使用mockito 2.x,支持 JDK 8默认方法.

有了mockito 1.x,这是不可能的,


老答案

不幸的是,它还不可能(mockito 1.10.19),来自README.mdgithub'页面

JDK8状态

如果你远离默认方法(也就是防守方法), Mockito应该可以正常使用JDK8 .Lambda的使用可能对Answers有效.我们目前不确定每个JDK8的功能,比如序列化使用lambda的模拟.我们欢迎错误报告和拉取请求(贡献指南).

编辑1:防御方法默认方法是同一件事的不同名称.

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

编辑2:更新了mockito自述文件,并相应地引用了此引号

  • 是的,它只是_default方法的另一个名称_ (2认同)
  • 好吧,那么,我想我会提交一个更新自述文件的拉取请求......我相信没有多少人知道这两个是同义词 (2认同)

Ash*_*eze 6

Mockito (this works on version 3) can use default methods. Here's the example code rewritten with JUnit 5 so it should work:

@ExtendWith(MockitoExtension.class)
class MockTest {
    @Mock(answer = Answers.CALLS_REAL_METHODS)
    private Foo foo;

    @Test
    void testDefaultMethodsWithMocks() {
        assertThat(foo.bar()).isEqualTo(42);
    }

    @FunctionalInterface
    private interface Foo {
        int foo();

        default int bar() {
            return 42;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

The calls real methods answer DOES work in the latest Mockito. As a general rule, the extensions make the creation of mocks more declarative, but the mock method also provides an overload which supports the default answer as shown in the @Mock annotation above: https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#mock-java.lang.Class-org.mockito.stubbing.Answer-


Jan*_*rek 5

我刚试过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);
Run Code Online (Sandbox Code Playgroud)