如果部分测试时间过长,如何从JUnit测试返回到main方法

时间:2014-12-16 14:59:03

标签: java testing junit timeout

我尝试使用main()方法运行junit:

public static void main(String... args) throws ClassNotFoundException, 
       IOException {
  //...
  logger.debug("className " + className + "methodName " + methodName);

  Request request = Request.method(Class.forName(className), methodName);
  return new JUnitCore().run(request);
}

我有一个带有10个命令的E2E测试(比方说)。它由JUnit运行,我想将命令3-5的运行时间限制为 X millis(其中 X 在运行时确定)。如果它的运行时间超过 X ,我想返回main()并打印一些内容。

我尝试了System.exit(),但它关闭了整个应用程序。我试过了:

public void setTimeOut(String criticalBlockTimeOutMilli) {
    if (criticalBlockTimeOutMilli != null) {
        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                E2eResult e2eResult = E2eResult.getInstance();
                e2eResult.status = E2eStatus.TIMEOUT;
                //System.exit(2);
            }
        };
        new Timer().schedule(timerTask, Long.parseLong(criticalBlockTimeOutMilli));
    }
}

public void setTimeOut(final Thread thread, String criticalBlockTimeOutMilli) {
    if (criticalBlockTimeOutMilli != null) {
        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                E2eResult e2eResult = E2eResult.getInstance();
                e2eResult.status = E2eStatus.TIMEOUT;
                thread.interrupt();
            }
        };
        new Timer().schedule(timerTask, Long.parseLong(criticalBlockTimeOutMilli));
    }
}

但即使超出限制,主线程仍会继续运行测试。你会建议什么?

2 个答案:

答案 0 :(得分:1)

单元测试可能不是解决此类性能测试的最佳方法。但是,如果出于某种原因必须这样做,请继续阅读......

使用ExecutorService以给定的超时运行所需的命令。如果超时到期,抛出你自己的异常,你可以在主线程中捕获:

@Test
public void yourTest() throws Exception {

  // Do commands 1-2

  ExecutorService service = Executors.newSingleThreadExecutor();
  Future<Void> result = service.submit(new Callable<Void>() {
    @Override
    public Void call() throws Exception {
      // call commands 3-5
      return null;
    }
  });

  try {
    result.get(42, TimeUnit.MILLISECONDS);
  } catch (TimeoutException e) {
    throw new YourOwnException();
  }

  service.shutdown();

  // Do commands 6-10
}

答案 1 :(得分:1)

一个相当简单的机制是使用BlockingQueue来表示测试已完成。如果您发现它没有,那么您可以interrupt它。这仅在测试正确响应被中断时才有效。

// Send FINISHED down this queue when test completes.
final BlockingQueue<Object> finished = new ArrayBlockingQueue<>(1);
// FINISHED cookie.
static final Object FINISHED = new Object();

public void test() throws InterruptedException {
    Thread test = new Thread(new Runnable() {

        @Override
        public void run() {
            // Do your stuff.
            // ...
            // Signal we finished.
            finished.add(FINISHED);
        }
    });
    // Start the test in it's own thread.
    test.start();
    try {
        // Wait for your time.
        if (FINISHED == finished.poll(5, TimeUnit.MILLISECONDS)) {
            // It completed! No problems.
        } else {
            // It hasn't finished! Interrupt it.
            test.interrupt();
        };
    } catch (InterruptedException ex) {
        // We were interrupted! Do something.
        test.interrupt();
        // Rethrow it.
        throw(ex);
    }
}

您可以通过添加&#34;已启动&#34;来扩展此机制。消息也是如此,以确保测试线程至少有机会运行。