使用JUnit运行测试用例时,在Eclipse Debug中禁用了Drop to frame功能

时间:2012-11-20 11:48:42

标签: java eclipse debugging junit

环境: Linux,Eclipse Juno,Java 7,JUnit

当一个简单的应用程序(带有main方法的java类)在调试模式下运行时,' Drop to Frame'功能在Eclipse中运行良好。但是,如果从junit测试用例中调用相同的方法,则“删除到帧”' Eclipse中禁用了该功能。从文档

  

注意此命令仅在当前VM支持drop to时可用   框架和所选的堆栈框架不是顶部框架或框架中的框架   原生方法。

正如我们在调试窗口中的堆栈帧中看到的那样,当运行junit测试用例时,有一个框架' NativeMethodAccessorImpl.invoke'这是原生的。我假设这是“掉到框架”的原因'被禁用。

如果这种推理是正确的,请告诉我,如果是,可以使用任何解决方法来解决此问题。

3 个答案:

答案 0 :(得分:8)

我在Windows下使用Eclipse Luna,Java 7。 情况仍然如下所述:对于紧跟在“NativeMethodAccessorImpl.invoke”框架之后的测试方法,禁用“Drop to frame”。 “Drop to frame”的禁用状态绑定到类canDropToFrame()中相应supportsDropToFrame()的方法org.eclipse.jdt.internal.debug.core.model.JDIStackFrame, (在我的发行版中)plugins/org.eclipse.jdt.debug_3.8.102.v20150115-1323/jdimodel.jar的一部分。 方法supportsDropToFrame()检查是否可以删除特定的帧,并测试

  1. JVM必须支持丢帧
  2. 框架不能是最顶层的框架
  3. 框架不得为原生
  4. 前一帧不得原生

所以Ramesh的假设是正确的。 这是测试3 + 4的原始代码段:

int index = 0;
JDIStackFrame frame = null;
while (index < frames.size()) {
    frame = (JDIStackFrame) frames.get(index);
    index++;
    if (frame.isNative()) {
        return false;
    }
    if (frame.equals(this)) {
        if (jdkSupport) {
            // JDK 1.4 VMs are currently unable to pop the
            // frame directly above a native frame
            if (index < frames.size()
                    && ((JDIStackFrame) frames.get(index))
                            .isNative()) {
                return false;
            }
        }
        return true;
    }
}

评论表明它是用JDK编写的1.4次,所以也许在此期间JVM现在也可以将帧丢弃到本机帧之上。

我创建了JDIStackFrame的修补版本,跳过了测试4。 现在,当在Junit测试方法中暂停时,“Drop to frame”已按预期启用。

但是当实际丢弃帧时,我收到一个错误消息框,上面写着 “com.sun.jdi.InternalException:回复时出现错误代码:32出现了弹出堆栈帧”。

我认为这是一个JDWP错误代码。 因此,似乎这样的“Drop to frame”在JDK 1.7中不起作用(不知道1.8),并且它不是Eclipse的东西。

答案 1 :(得分:0)

这是一个古老的版本,但是就目前而言,这仍然是Eclipse 2018-09,Java 1.8和testng作为测试运行程序的问题。解决方法(简单明了)是将测试的内容提取到另一种方法中,对其进行调试,然后将其内联。例如:

@Test
public void test() {
    // test goes here
    assertTrue(true);
}

一个人可以使用重构快捷方式来加快速度:选择测试的主体,按Alt + Shift + M,输入名称“ inner”,结果为:

@Test
public void test() {
    inner();
}

private void inner() {
    // test goes here and 'drop-to-frame' works well
    assertTrue(true);
}

调试完成后,在inner()内部按Alt + Shift + I将其内联。

答案 2 :(得分:0)

我总是通过在 @Test 函数和我可以将帧放入其中的 thunk 之间拆分来处理这个问题。

在 JDK-8 之前,我会这样做:

@Test
public void testSomeFooInBar() {
    drop_to_frame_testSomeFooInBar();
}

private void drop_to_frame_testSomeFooInBar() {
    assertTrue(somethingOrWhatever);
}

即使它很冗长,我还是坚持/坚持在测试函数之后调用我的thunks,名称表明它们的用途(“跳转/降帧”)。这总是必要的,因为总是有人在不阅读评论的情况下进行“重构”,并开始将 thunk 删除为“不必要的”。

使用 JDK 8 及更高版本,我这样做:

@Test
public void testSomeFooInBar() {
    final Runnable drop_to_frame = () -> {
        assertTrue(somethingOrWhatever);
    };
    jump_to_frame.run();
}

更简单。 Eclipse 将允许您在可运行的 lambda 内设置断点,并根据需要多次进入帧(假设您的逻辑具有足够的可重入性。)