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:我知道中断…-这就是我的意思,只有当测试正确响应被中断时,它才会起作用。