如何为"InterruptedException"编写单元测试

Hip*_*ter 12 java unit-testing

为了实现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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

eri*_*son 16

在调用之前addMessage(),请致电Thread.currentThread().interrupt().这将在线程上设置"中断"状态标志.

如果put()在a上进行呼叫时设置了中断状态,则即使不需要等待(锁是无争用的)LinkedBlockingQueue,InterruptedException也会引发中断状态put.

顺便说一下,达到100%覆盖率的一些努力会适得其反,实际上会降低代码质量.

  • +1,这是真的。目标是 80-85,您将避免所有类似的问题,并且仍然保持您的代码非常原始。 (2认同)
  • 这是一个非常残酷的解决方案,并且可能会产生意想不到的副作用。例如,我发现在一个测试方法中调用Thread.currentThread()。interrupt()会影响同一类中的所有测试方法,从而导致所有其他测试失败。我还发现,将其添加到任何测试类中会使Sonar报告0%的单元测试覆盖率(尚未发现原因)。 (2认同)

Pet*_*ans 13

使用像Easymock这样的模拟库并注入一个模拟的LinkedBlockingQueue

@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);
}
Run Code Online (Sandbox Code Playgroud)


ixi*_*ixi 10

如上所述,Thread.currentThread().interrupt()如果你抓住了它,就使用它InterruptedException,并且不会重新抛出它。

至于单元测试。这样测试:Assertions.assertThat(Thread.interrupted()).isTrue();. 它既检查线程是否被中断,又清除中断标志,这样就不会破坏其他测试、代码覆盖率或下面的任何内容。