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

Dav*_*ave 21 junit protected mocking mockito

我正在使用Mockito 1.9.5.如何模拟受保护方法返回的内容?我有这种受保护的方法......

protected JSONObject myMethod(final String param1, final String param2)
{
…
}
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试在JUnit中执行此操作时:

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

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

Joh*_*n B 31

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

几个选项:

  • 在与模拟类相同的包中声明您的测试
  • 如果可以的话,改变方法的可见性
  • 创建一个扩展模拟类的本地(内部)类,然后模拟这个本地类.由于该类是本地的,因此您可以看到该方法.

  • 当具有相同的包名但源在主文件夹中并且测试类在测试文件夹中时,方法 1 似乎不起作用 (3认同)
  • 我选择#3(创建一个具有覆盖受保护方法的公共方法的类,只调用super.method()) (2认同)

nic*_*mon 11

您可以使用 Spring 的 ReflectionTestUtils 按原样使用您的类,而无需更改它只是为了测试或将其包装在另一个类中。

public class MyService {
    protected JSONObject myProtectedMethod(final String param1, final String param2) {
        return new JSONObject();
    }

    public JSONObject myPublicMethod(final String param1) {
        return new JSONObject();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在测试中

@RunWith(MockitoJUnitRunner.class)
public class MyServiceTest {
    @Mock
    private MyService myService;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        when(myService.myPublicMethod(anyString())).thenReturn(mock(JSONObject.class));
        when(ReflectionTestUtils.invokeMethod(myService, "myProtectedMethod", anyString(), anyString())).thenReturn(mock(JSONObject.class));
    }
}
Run Code Online (Sandbox Code Playgroud)


Nye*_*fan 9

回应John B的答案中对选项3的代码示例的请求:

public class MyClass {
    protected String protectedMethod() {
        return "Can't touch this";
    }
    public String publicMethod() {
        return protectedMethod();
    }
}
Run Code Online (Sandbox Code Playgroud)
@RunWith(MockitoJUnitRunner.class)
public class MyClassTest {

    class MyClassMock extends MyClass {
        @Override
        public String protectedFunction() {
            return "You can see me now!";
        }
    }

    @Mock
    MyClassMock myClass = mock(MyClassMock.class);

    @Test
    public void myClassPublicFunctionTest() {
        when(myClass.publicFunction()).thenCallRealMethod();
        when(myClass.protectedFunction()).thenReturn("jk!");
    }
}
Run Code Online (Sandbox Code Playgroud)