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

zysjyyx4  于 12个月前  发布在  其他
关注(0)|答案(8)|浏览(110)

我正在使用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);


在最后一行,我得到一个编译错误“The method 'myMethod' is not visible.”我如何使用Mockito来模拟受保护的方法?如果这是答案,我愿意升级我的版本。

pcrecxhr

pcrecxhr1#

这不是Mockito的问题,而是普通的Java。从你调用方法的地方,你没有可见性。这就是为什么它是编译时问题而不是运行时问题。
有几个选择:

  • 在与模拟类相同的包中声明测试
  • 如果可以,请更改方法的权限
  • 创建一个局部(内部)类来扩展模拟的类,然后模拟这个局部类。因为这个类是局部的,所以你可以看到这个方法。
dl5txlt9

dl5txlt92#

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

public class MyClass {
    protected String protectedMethod() {
        return "Can't touch this";
    }
    public String publicMethod() {
        return protectedMethod();
    }
}

个字符

hsvhsicv

hsvhsicv3#

你可以使用Spring的ReflectionTestUtils来使用你的类,而不需要为了测试而改变它,或者把它 Package 在另一个类中。

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

    public JSONObject myPublicMethod(final String param1) {
        return new JSONObject();
    }
}

字符串
然后在测试中,

@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));
    }
}

wbrvyc0a

wbrvyc0a4#

我使用了doReturn()和Junit5的ReflectionSupport,就像下面这样。
[Note:我在Mockito 3.12.4上测试过]

ReflectionSupport.invokeMethod(
        mymock.getClass()
//              .getSuperclass()     // Uncomment this, if the protected method defined in the parent class.
                .getDeclaredMethod("myMethod", String.class, String.class),
        doReturn(myData).when(mymock),
        param1,
        param2);

字符串

zsbz8rwp

zsbz8rwp5#

John B是对的,这是因为你试图测试的方法是受保护的,这不是Mockito的问题。
在他列出的方法之上的另一个选择是使用反射来访问方法。这将允许您避免更改正在测试的方法,并避免更改用于编写测试的模式,我不得不自己做一些测试,因为我不允许更改现有的代码库,其中包括大量的私有方法,进行单元测试。
这些链接解释了反射以及如何很好地使用它,所以我将链接到它们而不是复制:

mzaanser

mzaanser6#

whiteBox.invokeMethod()可以很方便。

3ks5zfa0

3ks5zfa07#

MyService myService = new MyService() {
    MyService callProtectedMethod(String param1, String param2) {
        myMethod(param1, param2);
        return this;
    }
}.callProtectedMethod(param1, param2);

// your assertion here: trivial e.g. assertNotNull(myService);

字符串

tquggr8v

tquggr8v8#

public class Test extend TargetClass{
    @Override
    protected Object method(...) {
        return [ValueYouWant];
    }  
}

字符串
在Spring中,你可以像这样设置它的高优先级:

@TestConfiguration
public class Config {

    @Profile({"..."})
    @Bean("...")
    @Primary  // <------ high-priority
    public TargetClass TargetClass(){
        return new TargetClass() {
            @Override
            protected WPayResponse validate(...)  {
                return null;
            }
        };
    }
}


覆盖源bean也是一样的。

相关问题