为getStackTrace()获取不同的结果[2] .getMethodName()

为了记录目的,我创建了一个方法logTitle(),它打印出我们的TestNG测试的调用方法名称。 示例代码如下。

@Test
public void test1() throws Exception {
    method1();
}

public static void method1() throws Exception {
    Utils.logTitle(2);
}

...

public static void logTitle(Integer level) throws Exception {

    // Gets calling method name
    String method = Thread.currentThread().getStackTrace()[2].getMethodName();
    // This would get current method name
    switch (level) {
    case 1:
        logger.info("=======================================================");
        logger.info(method);
        logger.info("=======================================================");
        break;
    case 2:
        logger.info("------------------------------------");
        logger.info(method);
        logger.info("------------------------------------");
        break;
    case 3:
        logger.info("---------------------");
        logger.info(method);
        logger.info("---------------------");
        break;
    case 4:
        logger.info("--------- " + method + " ------------");
        break;
    default:
        logger.info(method);
    }
}

问题是我在两台不同的机器上得到了logTitle()的不同结果。

每个人的笔记本都能正确返回

2016-06-20 14:22:06 INFO  - ------------------------------------
2016-06-20 14:22:06 INFO  - method1
2016-06-20 14:22:06 INFO  - ------------------------------------

我们的开发人员unix框返回不同:

2016-06-20 14:42:26 INFO  - ------------------------------------
2016-06-20 14:42:26 INFO  - logTitle
2016-06-20 14:42:26 INFO  - ------------------------------------

这可以在其他人的笔记本电脑上正常工作,而不是在开发者unix机器上。 我认为dev unix box正在使用IBM的Java版本,而其他人都在使用Oracle的Java版本,但不确定这是不是罪魁祸首。

有任何想法吗?


我认为它的具体深度导致您的方案中出现问题2。

所以,而不是写作

String method = Thread.currentThread().getStackTrace()[2].getMethodName();

如果你写

StackTraceElement[] ste = Thread.currentThread().getStackTrace();
String method = null;
boolean doNext = false;
for (StackTraceElement s : ste) {
       if (doNext) {
          method = s.getMethodName();
          return;
       }
       doNext = s.getMethodName().equals("getStackTrace");
   }

它仅适用于JDK 1.5+

另一个选项如下:

String method = new Object(){}.getClass().getEnclosingMethod().getName();

或者一个较慢的选项将是:

String method = new Exception().getStackTrace()[0].getMethodName();

因为这会每次创建一个Exception实例。

希望能帮助你。


具有测试方法名称的更简单的方法是使用@BeforeMethod并注入Method 。 请参阅此处的TestNG文档。

只需将名称存储在某个地方并在日志中使用它(为什么不在@AfterMethod ?)


来自Javadoc:

某些虚拟机在某些情况下可能会忽略堆栈跟踪中的一个或多个堆栈帧。 在极端情况下,不允许有关此throwable的堆栈跟踪信息的虚拟机从此方法返回一个长度为零的数组。

所以,唯一可以保证的方法是使用方面,或者采用其他自定义方式收集堆栈跟踪。 但是,您可以将此方法与回退结合起来,以某种方式获取当前方法的名称(例如,当您的logTitle方法将被内联时)。 例如,可以在这里找到。 再次,没有保证,但更好的机会。

链接地址: http://www.djcxy.com/p/82415.html

上一篇: Getting different results for getStackTrace()[2].getMethodName()

下一篇: Java or any other language: Which method/class invoked mine?