Junit 如何使用Mockito模拟受保护的方法?

Junit 如何使用Mockito模拟受保护的方法?,junit,mocking,mockito,protected,Junit,Mocking,Mockito,Protected,我用的是Mockito 1.9.5。如何模拟从受保护方法返回的内容?我有这个受保护的方法 protected JSONObject myMethod(final String param1, final String param2) { … } 但是,当我尝试在JUnit中执行此操作时: final MyService mymock = Mockito.mock(MyService.class, Mockito.CALLS_REAL_METHODS); fina

我用的是Mockito 1.9.5。如何模拟从受保护方法返回的内容?我有这个受保护的方法

protected JSONObject myMethod(final String param1, final String param2)
{
…
}
但是,当我尝试在JUnit中执行此操作时:

    final MyService mymock = Mockito.mock(MyService.class, Mockito.CALLS_REAL_METHODS);        
    final String pararm1 = “param1”;
    Mockito.doReturn(myData).when(mymock).myMethod(param1, param2);

在最后一行,我得到一个编译错误“方法‘myMethod’不可见”。我如何使用Mockito来模拟受保护的方法?如果答案是这样,我愿意升级我的版本。

这不是Mockito的问题,而是普通旧java的问题。从调用方法的位置,您没有可见性。这就是为什么它是编译时问题而不是运行时问题

有两种选择:

  • 在与模拟类相同的包中声明测试
  • 如果可以,请更改方法的可见性
  • 创建扩展模拟类的本地(内部)类,然后模拟此本地类。因为类是本地的,所以您可以看到该方法

John B是对的,这是因为您尝试测试的方法受到保护,Mockito没有问题

在他列出的方法之上的另一个选择是使用反射来访问该方法。这将允许您避免更改正在测试的方法,并避免更改用于编写测试的模式以及存储这些测试的位置。有些测试不允许我更改现有的代码库,其中包括大量需要进行单元测试的私有方法,我不得不自己做这些测试

这些链接解释了反射以及如何很好地使用反射,因此我将链接到它们,而不是复制:


对John B答案中选项3的代码样本请求的响应:


公共类MyClass{
受保护字符串protectedMethod(){
返回“不能碰这个”;
}
公共字符串publicMethod(){
返回protectedMethod();
}
}

@RunWith(MockitoJUnitRunner.class)
公共类MyClassTest{
类MyClassMock扩展了MyClass{
@凌驾
公共字符串protectedMethod(){
return“你现在可以看到我了!”;
}
}
@嘲弄
MyClassMock myClass=mock(MyClassMock.class);
@试验
public void myClassPublicMethodTest(){
当(myClass.publicMethod()).thenCallRealMethod()时;
当(myClass.protectedMethod())。然后返回(“jk!”);
}
}

WhiteBox.invokeMethod()可能很方便。

您可以使用Spring的ReflectionTestUtils原封不动地使用您的类,而无需仅为测试而对其进行更改或将其包装到另一个类中

公共类MyService{
受保护的JSONObject myProtectedMethod(最终字符串参数1,最终字符串参数2){
返回新的JSONObject();
}
公共JSONObject myPublicMethod(最终字符串参数1){
返回新的JSONObject();
}
}
然后在测试中

@RunWith(MockitoJUnitRunner.class)
公共类MyServiceTest{
@嘲弄
私人MyService-MyService;
@以前
公共作废设置(){
initMocks(this);
when(myService.myPublicMethod(anyString())).thenReturn(mock(JSONObject.class));
当(ReflectionTestUtils.invokeMethod(myService,“myProtectedMethod”,anyString(),anyString())。然后返回(mock(JSONObject.class));
}
}
公共类测试扩展TargetClass{
@凌驾
受保护对象方法(…){
返回[value youwant];
}  
}
在春季,您可以将其设置为高优先级,如下所示:

@TestConfiguration
公共类配置{
@配置文件({…})
@豆(“…”)

@Primary//关于您发布的链接,我没有将反射与Mockito联系起来。您可以发布一些示例代码来说明如何使用Mockito模拟受保护的方法吗?他不是在调用受保护的方法(反射会有帮助),而是试图模拟受保护的方法我选择了选项#3(创建一个具有覆盖受保护方法的公共方法的类,而cih只调用super.method())方法1在具有相同包名时似乎不起作用,但源代码在主文件夹中,测试类在测试文件夹中
@Override
似乎不是必需的 ? 另外,
spy
不是比
mock
更合适吗 ?