2013-02-27 3 views
2

Я добавляю тестовые случаи в Test Suite следующим образом:Общие методы, которые можно построить обобщенный тип

for(String methodName : getPublicDeclaredMethods(TestA.class)) 
{ 
    this.addTest((new TestA(methodName))); 
} 

for(String methodName : getPublicDeclaredMethods(TestB.class)) 
{ 
    this.addTest((new TestB(methodName))); 
} 

Это равносильно тому, как это сделать:

this.addTest((new TestA("TEST_METHOD_1"))); 
this.addTest((new TestA("TEST_METHOD_2"))); 
this.addTest((new TestB("TEST_METHOD_1"))); 
this.addTest((new TestB("TEST_METHOD_3"))); // woops I forgot TEST_METHOD_2 

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

Мой код выше гарантирует, что я добавлю все тестовые случаи, определенные в определенном классе. Тем не менее, я хотел бы иметь метод, который выглядит примерно так: вместо

void <T> addTestCasesFromClass() 
{ 
    for(String methodName : getPublicDeclaredMethods(T.class)) 
    { 
     this.addTest((new T(methodName))); 
    } 
} 

Но я не знаю, как это делается в Java. Возможно ли это? TestA и TestB получены из теста класса.

ответ

1

Дженерики бесполезны здесь, так как вы не можете сделать что-то вроде new T. Но вы можете сделать это еще некоторое отражение. Учитывая, что все классы, которые вы передаете этому методу, имеют конструктор, который принимает ровно один аргумент String.

void addTestCasesFromClass(Class<?> clz) 
{ 
    for(String methodName : getPublicDeclaredMethods(clz)) 
    { 
     this.addTest(clz.getConstructor(String.class).newInstance(methodName)); 
    } 
} 

Вызов будет выглядеть примерно так

addTestCasesFromClass(TestA.class); 
addTestCasesFromClass(TestB.class); 

Если addTest методы только объекты определенного базового класса (пусть это будет TestBase), а затем изменить общий параметр clz в Class<? extends TestBase> clz ,

+0

Am Я прав, говоря, что этот метод бросает IllegalArgumentException, SecurityException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException? – Baz

+0

Звучит правильно, я оставил обработку исключений для краткости. Также я не знаю, как вы хотите обрабатывать исключения (если, например, 'clz' не предоставляет доступный конструктор, который принимает строку). – Stephan

1

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

Class<?> clazz = ... 
Object instance = clazz.newInstance(); 

Это рекомендуется использовать вместо getConstructor хотя.

Хорошим примером этого является метод List.toArray в java, он требует, чтобы вы передавали экземпляр массива, чтобы он мог иметь фактическую ссылку на класс, поскольку дженерики недоступны во время выполнения.

1

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

public <T> void addTestClassesFromClass(T item){ 
    try { 
     Constructor<?> constructor = item.getClass().getConstructor(String.class); 
     for(String methodName : getPublicDeclaredMethods(item.getClass())){ 
      this.addTest((constructor.newInstance(methodName))); 
     } 
    } catch (Exception e) { 
     System.out.println("Oh crap!"); 
    } 
} 
0

Вот моя попытка:

public void addTestCasesFromClass(Class<? extends Test> c) throws IllegalArgumentException, SecurityException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException 
{ 
    for(String methodName : getPublicDeclaredMethods(c)) 
    { 
     this.addTest((c.getDeclaredConstructor(String.class).newInstance(methodName))); 
    } 
} 
Смежные вопросы