假设我有以下界面:
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不支持调用默认实现吗?
答案 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有所帮助。