开发者

Accessing protected method in test case using Java Reflection

开发者 https://www.devze.com 2023-02-04 10:56 出处:网络
Am trying to obtain and invoke a protected method residing in a different class and also different package using Java Reflection.

Am trying to obtain and invoke a protected method residing in a different class and also different package using Java Reflection.

Class containing protected method:

package com.myapp;

public class MyServiceImpl {

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

Calling class:

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

The compiler throws this Exception:

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


The problem with your code is that the getDeclaredMethod function looks up a function both by name and by argument types. With the call

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

The code will look for a method retrieveItems() with no arguments. The method you're looking for does take an argument, a string, so you should call

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

This will tell Java to search for retrieveItems(String), which is what you're looking for.


You should to use link to created object instead of link to class in invoke method and use Method.setAccessible(true) invocation for unlock access:

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


Instead of using that tricky reflection stuff, why not simply create a derived class, which will have access to the protected method?

See Is it bad practice to use Reflection in Unit testing? for further thoughts.


If you put your testcases in the same package (com.myapp instead of com.myapp.tests) they will have access to protected (and default package level) members.

Then you can call service.retrieveMembers(status) directly.

If you are trying to separate the source from the tests, its usually better to use a different source directory (for instance a src directory and a test directory).


No reflection or inheritance is needed:

Put your MyTestCase under package com.myapp, as scope 'protected' is also 'package'. Then MyTestCase can access protected methods of MyServiceImpl.

0

精彩评论

暂无评论...
验证码 换一张
取 消