如何使用 JMockit MockUp 作为默认接口方法

How to use JMockit MockUp for default interface method

尝试在 Java 8 默认接口方法上应用 MockUp,JMockit 告诉我找不到该方法。这已在 JMockit 1.15、1.19 和 1.25 中尝试过。这是一个非常简单的用例:

@RunWith(JMockit.class)
public class TestTest {

    public interface MyInterface {
        default void foo(int f) {
            bar(String.valueOf(f));
        }

        void bar(String s);
    }

    public class MyClass implements MyInterface {
        public void bar(String s) {
            System.out.println(s);
        }
    }

    @Test
    public void testtest() throws Exception {
        new MockUp<MyClass>() {
            @Mock
            void foo(int i) {
                System.out.println("MOCKMOCK " + (i*2));
            }

            @Mock
            void bar(String s) {
                System.out.println("MOCK " + s);
            }
        };

        MyClass baz = new MyClass();

        baz.foo(5);
        baz.bar("Hello world");
    }

}

这让我犯了错误

java.lang.IllegalArgumentException: Matching real methods not found for the following mocks:
com.example.dcsohl.TestTest#foo(int)
    at com.example.dcsohl.TestTest.<init>(TestTest.java:29)
    at com.example.dcsohl.TestTest.testtest(TestTest.java:29)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    ...

如何@Mock这个方法?

使用@Mocked代替MockUp,它支持默认方法。

将您的用例稍微修改为 return 字符串而不是打印为标准输出以下解决方案将起作用。

import static org.junit.Assert.assertEquals;
import org.junit.Test;
import mockit.Expectations;

public class TestTest {

    public interface MyInterface {
        default String foo(int f) {
            return bar(String.valueOf(f));
        }

        String bar(String s);
    }

    public class MyClass implements MyInterface {
        public String bar(String s) {
            return s;
        }
    }

    @Test
    public void testtest() throws Exception {

        MyClass baz = new MyClass();

        new Expectations(MyClass.class) {{
            baz.foo(anyInt); result = "FOOMOCK";
            baz.bar(anyString); result = "BARMOCK";
        }};

        assertEquals(baz.foo(5), "FOOMOCK");
        assertEquals(baz.bar("Hello world"), "BARMOCK");
    }

}

在 jmockit github repository 的示例部分中概述了如何使用方法体(即默认或静态方法)模拟接口的许多有用示例。