Java Thread.currentThread().setUncaughtExceptionHandler()不能使用JUNIT?

Rob*_*ave 7 java junit

在下面的示例代码中,如果testMethod()通过main()运行,它按预期工作,但如果它是通过JUNIT运行,则不会调用MyUncaughtExceptionHandler.

对此有一些解释吗?

package nz.co.test;

import java.lang.Thread.UncaughtExceptionHandler;

import org.junit.Test;

public class ThreadDemo {

  private void testMethod() {
    Thread.currentThread().setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());

    Object b = null;
    // Cause a NPE
    b.hashCode();
  }

  @Test
  public void testJunit() {
    // Run via JUnit and MyUncaughtExceptionHandler doesn't catch the Exception
    testMethod(); 
  }

  public static void main(String[] args) {
    // Run via main() works as expected
    new ThreadDemo().testMethod();
  }

  static class MyUncaughtExceptionHandler implements UncaughtExceptionHandler {

    @Override
    public void uncaughtException(Thread t, Throwable e) {
      System.out.println("I caught the exception");
    } 
  }
}
Run Code Online (Sandbox Code Playgroud)

kan*_*kan 7

显然,setUncaughtExceptionHandler未处理的异常的集合处理程序.但是JUnit捕获了从测试方法抛出的所有异常.

无论如何,进行单元测试是一种奇怪的方式.单元测试应该测试您的代码,而不是JVM规范.

我想像这样的单元测试:

public class MyUncaughtExceptionHandlerTest
{
  @Mock Thread thread;
  MyUncaughtExceptionHandler testObject = new MyUncaughtExceptionHandler();

  @Before
  public void setUp()
  {
     MockitoAnnotations.initMocks(this);
  }

  @Test
  public void handleNpeShouldDoOneThing()
  {
    testObject.handleException(thread, new NullPointerException());
    //verify(oneThing)
  }

  @Test
  public void handleOomShouldDoSomethingElse()
  {
    testObject.handleException(thread, new OutOfMemoryError());
    //verify(somethingElse)
  }
}
Run Code Online (Sandbox Code Playgroud)


Evg*_*eev 6

这是因为JUnit捕获并处理了测试中抛出的所有异常,因此UncaughtExceptionHandler不会获取任何未捕获的异常.它在org.junit.runners.ParentRunners中完成

...
    protected final void runLeaf(Statement statement, Description description,
            RunNotifier notifier) {
        EachTestNotifier eachNotifier = new EachTestNotifier(notifier, description);
        eachNotifier.fireTestStarted();
        try {
            statement.evaluate();   <-- test method execution is called from here
        } catch (AssumptionViolatedException e) {
            eachNotifier.addFailedAssumption(e);
        } catch (Throwable e) {
            eachNotifier.addFailure(e);
        } finally {
            eachNotifier.fireTestFinished();
        }
    }
Run Code Online (Sandbox Code Playgroud)