使用Java Reflection访问测试用例中的受保护方法

时间:2011-01-12 00:21:11

标签: java reflection junit protected

尝试使用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()

5 个答案:

答案 0 :(得分:25)

代码的问题在于getDeclaredMethod函数通过名称和参数类型查找函数。通过电话

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

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

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

这将告诉Java搜索retrieveItems(String),这正是您正在寻找的。

答案 1 :(得分:6)

为什么不简单地创建一个可以访问受保护方法的派生类,而不是使用那些棘手的反射内容?

有关进一步的想法,请参阅Is it bad practice to use Reflection in Unit testing?

答案 2 :(得分:4)

如果您将测试版放在同一个软件包中(com.myapp而不是com.myapp.tests),他们可以访问受保护的(以及默认包成员。

然后您可以直接致电service.retrieveMembers(status)

如果您尝试将源与测试分开,通常最好使用不同的源目录(例如src目录和test目录。)

答案 3 :(得分:2)

不需要反思或继承:

将您的MyTestCase置于 com.myapp下,因为“受保护”范围也是“包”。 然后MyTestCase可以访问MyServiceImpl的受保护方法。

答案 4 :(得分: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");
}