使用 Java 反射在测试用例中访问受保护的方法

2022-09-02 00:44:24

我正在尝试使用Java Reflection获取并调用驻留在不同类和不同包中的受保护方法。

包含受保护方法的类:

package com.myapp;

public class MyServiceImpl {

   protected List<String> retrieveItems(String status) {
         // Implementation
   }
}

调用类:

package xxx.myapp.tests;

import com.myapp.MyServiceImpl;

public class MyTestCase {

    List<String> items;

    public void setUp() throws Exception {

         MyServiceImpl service = new MyServiceImpl();
         Class clazz = service.getClass();

         // Fails at the next line:
         Method retrieveItems = clazz.getDeclaredMethod("retrieveItems");

         // How to invoke the method and return List<String> items?
         // tried this but it fails?
         retrieveItems.invoke(clazz, "S");
    }
}

编译器将引发以下异常:

java.lang.NoSuchMethodException: com.myapp.MyServiceImpl.retrieveItems()

答案 1

代码的问题在于,该函数按名称和参数类型查找函数。通过呼叫getDeclaredMethod

Method retrieveItems = clazz.getDeclaredMethod("retrieveItems");

代码将查找没有参数的方法。您要查找的方法确实需要一个参数,一个字符串,因此您应该调用retrieveItems()

Method retrieveItems = clazz.getDeclaredMethod("retrieveItems", String.class);

这将告诉 Java 搜索 ,这就是您要查找的内容。retrieveItems(String)


答案 2

您应该使用指向已创建对象的链接,而不是在 invoke 方法中链接到类,并使用 Method.setAccessible(true) 调用进行解锁访问:

public void setUp() throws Exception {
    MyServiceImpl service = new MyServiceImpl();
    Class<?> clazz = service.getClass();
    Method retrieveItems = clazz.getDeclaredMethod("retrieveItems", String.class);
    retrieveItems.setAccessible(true);
    items = (List<String>)retrieveItems.invoke(service, "S");
}