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

Pac*_*ver 20 java reflection junit protected

我试图使用Java Reflection获取和调用驻留在不同类中的受保护方法以及不同的包.

包含受保护方法的类:

package com.myapp;

public class MyServiceImpl {

   protected List<String> retrieveItems(String status) {
         // Implementation
   }
}
Run Code Online (Sandbox Code Playgroud)

通话课程:

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");
    }
}
Run Code Online (Sandbox Code Playgroud)

编译器抛出此异常:

java.lang.NoSuchMethodException: com.myapp.MyServiceImpl.retrieveItems()
Run Code Online (Sandbox Code Playgroud)

tem*_*def 25

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

Method retrieveItems = clazz.getDeclaredMethod("retrieveItems");
Run Code Online (Sandbox Code Playgroud)

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

Method retrieveItems = clazz.getDeclaredMethod("retrieveItems", String.class);
Run Code Online (Sandbox Code Playgroud)

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


Rae*_*ald 6

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

请参阅在单元测试中使用反射是不好的做法?进一步的想法.

  • -1 - 它没有回答根问题.如何通过Java中的反射访问受保护的方法? (6认同)
  • -1 - "我试图使用Java Reflection获取和调用驻留在不同类中的受保护方法以及不同的包." 这是意图; 你怎么知道这不像学校的作业?似乎告诉他创建一个派生类(导致更多代码行)就像回答"我想用刀开一罐金枪鱼"和"使用开罐器"这样的问题. (2认同)

BeC*_*ase 6

您应该在 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");
}
Run Code Online (Sandbox Code Playgroud)