是否可以使用Mockito的doCallRealMethod调用接口的默认实现?

时间:2014-11-25 16:14:05

标签: mockito

假设我有以下界面:

public interface ISomething {

    default int doStuff() {
        return 2 * getValue();
    }

    int getValue();
}

当我现在模仿这个界面时:

@Mock
private ISomething _something;

@Before
public void setup() {
    doCallRealMethod().when(_something).doStuff();
}

并尝试测试doStuff()方法,如下所示:

@Test
public void testDoStuff() {
    when(_something.getValue()).thenReturn(42);
    assertThat("doStuff() returns 84", _something.doStuff(), is(84));
}

我希望测试能够成功,但我得到了:

org.mockito.exceptions.base.MockitoException:
Cannot call real method on java interface. Interface does not have any implementation!
Calling real methods is only possible when mocking concrete classes.

我尝试使用这样的抽象类继承ISomething

public abstract class Something implements ISomething {
}

并像上面那样模拟这个类。通过这种方法,我得到了同样的结果。

Mockito不支持调用默认实现吗?

2 个答案:

答案 0 :(得分:3)

那是对的。目前版本的Mockito并不支持这一点。你可以raise a feature request here。请注意,它似乎与发行版1.10.0中修复的问题456有关,因此请确保首先在最新版本中对此进行测试。

答案 1 :(得分:0)

我正在使用Mockito 1.9.5进行项目,遇到了与您发现的问题相同的问题。由于构建服务器的工作方式,我们无法升级Mockito。我们遇到的问题是在编写具体子类的单元测试时,因为我们无法在模拟对象中存根或将接口的默认方法包括在内(与示例稍有不同)。

这是使用您的模型的示例子类:

public class ConcreteSomething implements ISomething {

    @Override
    int getValue()
    {
        return 42;
    }
}

然后在单元测试类中,我们显式创建了一个私有内部类。此类使用接口的默认实现覆盖了受测具体类(即ConcreteSomething)的所有默认方法。因此,在此示例中,类似:

private class ConcreteSomethingDefaultImpl extends ConcreteSomething {

    @Override
    int doStuff() {
        return super.doStuff();
    }
}

对于我们来说,使用mock(ConcreteSomething.class)制作的模拟程序无法使用doCallRealMethod()来调用其默认方法,但是mock(ConcreteSomethingDefaultImpl.class)可以而且更重要的是,它是正在使用的界面。

我希望对任何受约束的人都可以使用特定版本的Mockito有所帮助。