Подтвердить что ты не робот

Доступ к защищенному методу в тестовом примере с использованием Java Reflection

Я пытаюсь получить и вызывать защищенный метод, находящийся в другом классе, а также другой пакет с использованием 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()

Спасибо, что нашли время, чтобы прочитать это.

4b9b3361

Ответ 1

Проблема с вашим кодом заключается в том, что функция getDeclaredMethod выполняет поиск функции как по имени, так и по типам аргументов. При вызове

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

Код будет искать метод retrieveItems() без аргументов. Метод, который вы ищете, принимает аргумент, строку, поэтому вы должны позвонить

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

Это скажет Java для поиска retrieveItems(String), который вы ищете.

Ответ 3

Если вы помещаете свои тестовые теги в один и тот же пакет (com.myappвместо com.myapp.tests), они будут иметь доступ к элементам protected по умолчанию).

Затем вы можете напрямую вызвать service.retrieveMembers(status).

Если вы пытаетесь отделить источник от тестов, обычно лучше использовать другой исходный каталог (например, каталог src и каталог test).

Ответ 4

Не требуется никакого отражения или наследования:

Поместите ваш MyTestCase в пакет com.myapp, так как область действия "protected" также является "пакетом". Затем MyTestCase может получить доступ к защищенным методам MyServiceImpl.

Ответ 5

Вам следует использовать ссылку на созданный объект вместо ссылки на класс в методе 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");
}