如何测试InterruptedException

6

我有以下的方法,它运行良好。 我正在尝试测试抛出InterruptedException的情况。这是我目前的测试方式,如果我只运行这个单独的测试就会起作用。 但是,如果我要运行测试类中剩余的5个测试,则有些测试开始失败。 当我单独运行它们时,所有测试都通过,因此很明显我的测试中的线程中断影响了其他测试。 如何编写测试,使其不影响其他测试?

@Component
class A{
    @Autowired
    private Helper helper;

    private static ExecutorService executor = Executors.newFixedThreadPool(10);

    // static variable in class
    private final Future<String> number = executor.submit(() -> helper.method());

    //method to be tested 
    public String getNumber() {
        try {
            return this.number.get();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new CustomException1();
        } catch (ExecutionException e) {
            throw new CustomException2();
        }
    }
}

@RunWith(MockitoJUnitRunner.class)
clas ATest{

    @InjectMocks
    private A a;

    @Mock
    private Helper helper;

    // this is my test method which passes when ran individually. But will affect other tests if everything is ran same time. 
    @Test
    public void testMethod() {

        when(helper.method()).thenReturn("222");
        String num = a.getNumber();

        // doing this on purpose so I would land inside the catch. This line is causing issues.
        Thread.currentThread().interrupt();

        try {
            assertEquals("222", num);
        }catch (CustomException1 e){
            // I will land here for this test as expected
            // do some assertions
        }

        // Thread.currentThread().interrupt(); // Tried calling it again here to clear the flag but doesn't work. 
    }

    // another few tests ..... 
}

状态可以通过使用 Thread.interrupted() 方法来清除。Thread.currentThread().interrupt(); 设置标志 - 它不会清除它。然而,我建议重新考虑设计,并使您的线程池可注入,并进一步将任务与执行器分离。 - Michał Krzywański
被中断在实际检查线程是否被中断之前几乎没有任何意义 - 通常情况下,这些是抛出“InterruptedException”的线程。因此,您应该显示受影响的其他测试。 - tevemadar
这里有些不对劲。中断状态只对当前线程可见。即使测试在并行运行,一个线程的中断状态也不会影响其他线程运行的测试。按照现有代码(第二个interrupt()被注释掉),当此测试退出时,中断状态是清晰的。我怀疑问题只会在取消注释主题测试后的第二个interrupt()调用时出现。 - erickson
3个回答

1
我认为最好的方法是模拟中断异常。
when(helper.method())).thenThrow(InterruptedException.class);

但是你也可以通过调用该方法来清除中断标志:
Thread.interrupted()

5
这里的第一个解决方案不正确。Mockito 不允许抛出已检查异常。执行此操作将导致以下结果:org.mockito.exceptions.base.MockitoException: Checked exception is invalid for this method! Invalid: java.lang.InterruptedException - Radioactive

0

鉴于被接受的答案在使用时会抛出异常,正如Radioactive所指出的那样,我想分享一个使用Mockito测试此问题的解决方法,它使用了willAnswer()方法。代码大致如下:

import static org.mockito.BDDMockito.given;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
class Test {
    @Test
    void test() {    
        given(helper.method()).willAnswer(invocation -> {
            throw new InterruptedException();
        });
        ...
    }
}

0
你应该模拟你的Future返回InterruptedException
尝试这个。
@RunWith(MockitoJUnitRunner.class)
public class ATest {

@Test(expected = CustomException1.class)
public void testMethod() throws ExecutionException, InterruptedException {
    Future future = mock(Future.class);
    when(future.get()).thenThrow(new InterruptedException());
    A a = new A(future);

    a.getNumber();
}

// another few tests .....

}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接