Запустите тест JUnit против произвольного загруженного класса - PullRequest
0 голосов
/ 25 февраля 2011

В рамках более крупного проекта я пытаюсь достичь чего-то, что, я не уверен, возможно, поэтому я с нетерпением жду, если у кого-нибудь есть какие-либо предложения!

Общая система:
В целом, моя система должна быть в состоянии обеспечить тестовый класс JUnit, который соответствует некоторому предоставленному интерфейсу.Затем будут даны классы, которые не реализуют этот интерфейс, но должны быть проверены, чтобы увидеть, смогут ли они (иначе, если они реализуют все необходимые методы).Если это так, то должно произойти какое-то преобразование, чтобы к нему мог быть запущен тестовый класс JUnit.

До сих пор я реализовал:
- Пакет, который загружает другие классы спуть и имя, используя URLClassLoader
- пакет, который запускает тестовый пример JUnit и возвращает результаты, используя JUnitCore

Проблема:
1. Сначала, как могЯ запускаю тест JUnit для класса, который реализует интерфейс, когда тест спроектирован так, чтобы соответствовать интерфейсу?Как я (во время выполнения) диктую, что экземпляр, проверяемый интерфейсом, является загруженным классом?

  1. Можно ли затем расширить это так, чтобы я мог i) убедиться, что он соответствует интерфейсу (я предполагаю, что с помощью Reflection проверяем соответствующие методы?), А затем ii) изменить этот класс таким образомчто его можно протестировать с помощью тестового класса JUnit?

Спасибо за любые советы, которые могут помочь решить эту проблему.Я понимаю, что моего описания, возможно, не хватает, поэтому, пожалуйста, прокомментируйте, если у вас есть какая-либо дополнительная информация, которая поможет вам дать любой ответ!

Ответы [ 4 ]

1 голос
/ 25 февраля 2011

Если вы хотите создать произвольный класс для реализации данного интерфейса во время выполнения, если его открытый API-интерфейс соответствует интерфейсу, у вас есть несколько опций в Java.Создание java.lang.Proxy для объединения целевого класса, простейший способ раскрытия YourInterface.

YourInterface i = (YourInterface) Proxy.newProxyInstance(
        this.getClass().getClassLoader(), 
        new Class[]{YourInterface.class},
        new InvocationHandler() {

    @Override
    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
        //run method on your target class here using reflection
    }

 });

Вы также можете использовать миксины в AspectJ или создать подкласс своего целевого класса с помощью CGLIB и добавить интерфейс во время выполнения.Но прокси-подход не так сложен для реализации.

1 голос
/ 25 февраля 2011

как я могу запустить тест JUnit для класса, который реализует интерфейс, если тест спроектирован так, чтобы соответствовать интерфейсу

Поскольку у вас есть класс, вы можете использовать метод isAssignableFromпредлагается классом таким образом, что

Class loadedJunitClass = clazz;
MyInterface impl = null;
if(MyInterface.class.isAssignableFrom(loadedJunitClass )){
    impl = (MyInterface) loadedJunitClass.newInstance();
}

По второму вопросу вы можете проверить каждый метод и посмотреть 1. Если существует метод с таким же именем метода, как определено в интерфейсе, 2. Если методтип возвращаемого значения совпадает с интерфейсом и 3. Если типы и длина параметра метода совпадают.Конечно, 2 и 3 могут быть сложными, чтобы получить право.

В этот момент я просто создал бы экземпляр этого интерфейса (анонимный или закрытый класс), создал newInstance этого соответствующего класса.И вызывать методы через отражение в методах интерфейса.

Вот как вы можете сделать это с помощью отражения.Я не советую рефлексию, как вы можете себе представить :)

1 голос
/ 25 февраля 2011

За первую часть вашего вопроса; если у вас есть загруженный экземпляр класса для класса, который вы хотите протестировать, вы можете создать его с помощью newInstance (), если у него есть конструктор по умолчанию, или с помощью методов getConstructor, если вам нужно передать параметры. Вы должны быть в состоянии получить этот экземпляр класса из загрузчика классов.

Для второй части. Вы должны иметь возможность проверять открытые методы с помощью getMethods () (снова в экземпляре Class), а затем просматривать возвращаемый массив для поиска нужных методов. В классе Method есть методы, которые будут возвращать информацию о параметрах, исключениях и типе возвращаемого значения, чтобы проверить, что они вам нужны.

Однако я почти уверен, что невозможно изменить класс во время выполнения, чтобы добавить интерфейс. Это может быть возможно путем изменения байтового кода, но я не знаю об этом.

Альтернативой может быть написание теста для вызова всего метода с помощью отражения, тогда не имеет значения, какой тип объекта, просто у него есть правильные методы (которые вы уже проверили).

1 голос
/ 25 февраля 2011

Вы можете делать все, что вы хотите с отражением API. Похоже, вы должны начать с учебника , а затем вернуться сюда для конкретных вопросов. Имея объект Class, вы можете проверить, реализует ли он данный интерфейс, создать его экземпляр, а затем обработать его как любой другой класс.

Редактировать: Я не думаю, что понял это из вашего вопроса, но в этом случае вы ищете Proxy часть API отражения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...