动态获取注释值,而不是硬编码类/方法名称以获取注释值

时间:2017-12-13 06:54:38

标签: java reflection

我在testNG上运行了一些测试,它们将在测试方法上注释测试数据类型,我使用通用的方法根据测试方法中的注释值读取测试数据。这里的问题是,我无法指定类或方法名称来读取注释,因为将会有不同类的不同/多个测试方法将读取测试数据。所以我正在寻找一种从这种常用方法动态读取注释的方法,基于哪种测试方法正在寻找测试数据。

请查看以下代码段以获得更清晰的信息。

public class MyClass1 {

    @Test
    @testDataParam(testDataType="excel")
    public void test1() {

        DataTable dataTable = new DataTable();
        dataTable.getValue();
        //Some test that reads from specified test data type
    }

}

public class MyClass2 {

    @Test
    @testDataParam(testDataType="json")
    public void test2() {

        DataTable dataTable = new DataTable();
        dataTable.getValue();
        //Some test that reads from specified test data type
    }

}

public class GetTestData {

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface testDataParam {
        String testDataType();
    }

}

public class DataTable {

    public void setDataTable() {

        // get annotation from test methods, test methods will be different for
        // different test, so i can not mention specific class or method here to read
        // annotation.

        // if test data type is excel, read data from excel
        // if test data type is json, read data from json
    }

    public String getValue() {

        // return value from specified data type excel/json
        return "";
    }
}

2 个答案:

答案 0 :(得分:2)

由于带注释的方法都没有参数,您可以简单地询问堆栈跟踪并查找方法以找到注释。

以下是一个例子:

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface TestData {
    String value();
}
public class MyClass1 {
    @TestData("Foo")
    public void test1() {
        Util.doSomething();
    }
}
public class Util {
    public static void doSomething() {
        for (StackTraceElement stackTrace : Thread.currentThread().getStackTrace()) {
            try {
                TestData annotation = Class.forName(stackTrace.getClassName())
                                           .getDeclaredMethod(stackTrace.getMethodName())
                                           .getAnnotation(TestData.class);
                if (annotation != null)
                    System.out.println("Test data is: " + annotation.value());
            } catch (Exception e) {
                // Ignore
            }
        }
    }
}

如果执行test1()方法,则会得到此输出:

Test data is: Foo

答案 1 :(得分:0)

我必须用编码问题解决这个问题。我只有一半的解决方案。

为了获取类,我使用了Fast Classpath Scanner来获取包中声明的所有类和子类。然后执行result.classNamesToClassRefs(result.getNamesOfAllClasses())以获取类列表

Class类型有一个方法,允许您获取其中的所有声明的方法,即[class object].getDeclaredMethods()。要获得Class,您需要执行MyClass1.classnew MyClass1().getClass()

要从Method返回的getDeclaredMethods()数组中获取所需方法,可以调用method.getAnnotation(Test.class)并检查它是否为空。如果不是,您可以使用:

testDataParam annotation = method.getAnnotation(testDataParam.class);
Sting dataType = annotation.testDataType();

从注释中提取数据类型。

完整:

//Put the classes into a Class<?> array
FastClasspathScanner scanner = new FastClasspathScanner("YOUR PACKAGE HERE");
ScanResult result = scanner.scan();

for (Class<?> cls : result.classNamesToClassRefs(result.getNamesOfAllClasses())) {
    for (Method method : cls.getDeclaredMethods()) {
        if (method.getAnnotation(Test.class) != null) {
            testDataParam annotation = method.getAnnotation(testDataParam.class);
            Sting dataType = annotation.testDataType();
            //Do what you want with this
        }
    }
}