Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如果部分测试花费的时间太长,如何从JUnit测试返回到main方法_Java_Testing_Junit_Timeout - Fatal编程技术网

Java 如果部分测试花费的时间太长,如何从JUnit测试返回到main方法

Java 如果部分测试花费的时间太长,如何从JUnit测试返回到main方法,java,testing,junit,timeout,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(class

我尝试从我的
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);
}
我有一个E2E测试,有10个命令(比如说)。它由JUnit运行,我想将命令的运行时间限制为3-5到X毫秒(其中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));
    }
}
但是主线程继续运行测试,即使超出了限制。您有什么建议?

单元测试可能不是解决此类性能测试的最佳方法。然而,如果有什么原因必须这样做,请继续阅读

使用
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
}
@测试
public void yourTest()引发异常{
//执行命令1-2
ExecutorService=Executors.newSingleThreadExecutor();
未来结果=service.submit(new Callable()){
@凌驾
public Void call()引发异常{
//调用命令3-5
返回null;
}
});
试一试{
get(42,时间单位为毫秒);
}捕获(超时异常e){
抛出新的YourOwnException();
}
service.shutdown();
//执行命令6-10
}

一个相当简单的机制是使用
阻塞队列来指示测试已完成。如果你发现它没有,你可以中断它。只有当测试正确响应被中断时,这才有效

// 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);
    }
}
//测试完成时,发送已完成此队列。
最终阻塞队列完成=新的ArrayBlockingQueue(1);
//成品饼干。
静态最终对象已完成=新对象();
public void test()引发InterruptedException{
线程测试=新线程(新可运行(){
@凌驾
公开募捐{
//做你的事。
// ...
//我们结束了。
完成。添加(完成);
}
});
//在自己的线程中启动测试。
test.start();
试一试{
//等待时机。
if(FINISHED==FINISHED.poll(5,TimeUnit.ms)){
//完成了!没问题。
}否则{
//还没完!打断一下。
test.interrupt();
};
}捕获(中断异常例外){
//我们被打断了!做点什么。
test.interrupt();
//重播它。
投掷(ex);
}
}

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

您应该使用
ExecutorService
而不是
Timer
扫描。请提供一个示例,因为我仍然看不出如果您进行编辑,它会有多大帮助,是的,如果(FINISHED==FINISHED.poll(5,TimeUnit.millizes)){
可以工作,因为您总是使用字符串常量,但是看到字符串与
=
进行比较仍然会让我感到不安,因为如果以不使用常量的方式更改代码(根据墨菲定律,你知道有人会这么做),代码被丢弃。@hoverCraftFullOfels-为了稍微好一点,将其更改为
Object
。我可能会将其移动到
enum状态{start,FINISHED}
在real code中可以获得最佳的类型安全性,但答案会变得过于复杂。但我想限制一些命令的执行时间,而不是整个测试。我知道中断只会在中断的线程中发出一个标志,而不会停止其当前线程task@user1065869但是我想…-那就只为那些命令做这个。Re:我知道中断…-这就是我的意思,只有当测试正确响应被中断时,它才会起作用。