java 如何为“InterruptedException”编写单元测试
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3704747/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to write unit test for "InterruptedException"
提问by HipsterZipster
In attempts of 100% code coverage, I came across a situation where I need to unit test block of code that catches an InterruptedException
. How does one correctly unit test this? (JUnit 4 syntax please)
在尝试 100% 代码覆盖率时,我遇到了一种情况,我需要对捕获InterruptedException
. 如何正确地进行单元测试?(请使用 JUnit 4 语法)
private final LinkedBlockingQueue<ExampleMessage> m_Queue;
public void addMessage(ExampleMessage hm) {
if( hm!=null){
try {
m_Queue.put(hm);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
回答by erickson
Right before invoking addMessage()
, call Thread.currentThread().interrupt()
. This will set the "interrupt" status flag on the thread.
在调用之前addMessage()
,调用Thread.currentThread().interrupt()
. 这将在线程上设置“中断”状态标志。
If the interrupted status is set when the call to put()
is made on a LinkedBlockingQueue
, an InterruptedException
will be raised, even if no waiting is required for the put
(the lock is un-contended).
如果在put()
对 a进行调用时设置了中断状态LinkedBlockingQueue
,InterruptedException
则将引发an ,即使不需要等待put
(锁是无争用的)。
By the way, some efforts to reach 100% coverage are counter-productive and can actually degrade the quality of code.
顺便说一句,达到 100% 覆盖率的一些努力会适得其反,实际上会降低代码质量。
回答by Peter Tillemans
Use a mocking library like Easymock and inject a mock LinkedBlockingQueue
使用像 Easymock 这样的模拟库并注入模拟 LinkedBlockingQueue
i.e.
IE
@Test(expected=InterruptedException.class)
public void testInterruptedException() {
LinkedBlockingQueue queue = EasyMock.createMock(LinkedBlockingQueue.class);
ExampleMessage message = new ExampleMessage();
queue.put(message);
EasyMock.expectLastCall.andThrow(new InterruptedException());
replay(queue);
someObject.setQueue(queue);
someObject.addMessage(msg);
}
回答by ixi
As stated above just make use Thread.currentThread().interrupt()
if you caught InterruptedException
and isn't going to rethrow it.
如上所述,Thread.currentThread().interrupt()
如果您抓住了就可以使用它,InterruptedException
并且不会重新抛出它。
As for the unit testing. Test this way: Assertions.assertThat(Thread.interrupted()).isTrue();
. It both checks that the thread was interrupted and clears the interruption flag so that it won't break other test, code coverage or anything below.
至于单元测试。这样测试:Assertions.assertThat(Thread.interrupted()).isTrue();
. 它既检查线程是否被中断,又清除中断标志,这样它就不会破坏其他测试、代码覆盖率或以下任何内容。
回答by Michal Kordas
Another option is to delegate dealing with InterruptedException
to Guava's Uninterruptibles
, so you don't need to write and test your custom code for it:
另一种选择是将处理委托InterruptedException
给Guava的Uninterruptibles
,因此您无需为它编写和测试您的自定义代码:
import static com.google.common.util.concurrent.Uninterruptibles.putUninterruptibly;
private final LinkedBlockingQueue<ExampleMessage> queue;
public void addMessage(ExampleMessage message) {
putUninterruptibly(queue, message);
}
回答by wtsolid
One proper way could be customizing/injecting the ThreadFactory for the executorservice and from within the thread factory, you got the handle of the thread created, then you can schedule some task to interrupt the thread being interested.
一种正确的方法可能是为 executorservice 自定义/注入 ThreadFactory,并从线程工厂内部获得创建的线程的句柄,然后您可以安排一些任务来中断感兴趣的线程。
Demo code part for the overwrited method "newThread" in ThreadFactory:
ThreadFactory 中覆盖方法“newThread”的演示代码部分:
ThreadFactory customThreadfactory new ThreadFactory() {
public Thread newThread(Runnable runnable) {
final Thread thread = new Thread(runnable);
if (namePrefix != null) {
thread.setName(namePrefix + "-" + count.getAndIncrement());
}
if (daemon != null) {
thread.setDaemon(daemon);
}
if (priority != null) {
thread.setPriority(priority);
}
scheduledExecutorService.schedule(new Callable<String>() {
public String call() throws Exception {
System.out.println("Executed!");
thread.interrupt();
return "Called!";
}
},
5,
TimeUnit.SECONDS);
return thread;
}
}
Then you can use below to construct your executorservice instance:
然后你可以使用下面来构建你的 executorservice 实例:
ExecutorService executorService = Executors.newFixedThreadPool(3,
customThreadfactory);
Then after 5 seconds, an interrupt signal will be sent to the threads in a way each thread will be interrupted once in executorservice.
然后在 5 秒后,会以每个线程在 executorservice 中被中断一次的方式向线程发送中断信号。