简体   繁体   English

如何用Java测试一个使用sleep()的方法?

[英]How to test a method using sleep() with Java?

I have the following method and I am struggling to get 100% code coverage. 我有以下方法,我正在努力获得100%的代码覆盖率。

public final class SleepingHelper {
    public static void sleepInMillis(Duration timeOfNextTry) {
        try {
            Thread.sleep(timeOfNextTry.toMillis());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

The question is how can I force Thread.sleep to throw an exception? 问题是如何强制Thread.sleep抛出异常?

Edit: since it was marked as duplicate, I am still wondering what I would assert in the test ? 编辑:因为它被标记为重复,我仍然想知道我会在测试中断言什么? The other question Is more generic. 另一个问题是更通用的。

You need to interrupt it from another thread. 你需要从另一个线程中断它。 For example: 例如:

 Thread t = new Thread() {
     public void run () {
        SleeperMillis.sleepInMillis(new Duration(10000000l));
     }
 }.start();
 Thread.sleep(100); // let the other thread start
 t.interrupt;

You don't need to actually interrupt the thread. 您不需要实际中断线程。 You can use PowerMockito to mock the static method Thread.sleep() 您可以使用PowerMockito来模拟静态方法Thread.sleep()

@RunWith(PowerMockRunner.class)
@PrepareForTest(Thread.class)
public class TestClass {

    @Test
    public void testSleepInMillis() throws Exception {
        PowerMockito.mockStatic(Thread.class);
        PowerMockito.doThrow(new InterruptedException ()).when(Thread.class);

        try {
            SleepHelper.sleepInMillis(11);
            fail("expected exception");
        } catch (InterruptedException e) {
            System.out.println("all good");
        }

    }

You don't test it, because you can't assert its results, and you can't assert it because Thread.sleep is not accurate or guaranteed to sleep for this duration of time, and the test results will differ from run to run. 你不测试它,因为你无法断言它的结果,并且你不能断言它因为Thread.sleep不准确或保证在这段时间内没有睡眠,并且测试结果会因运行而不同。

Mocking is a better option here. Mocking是一个更好的选择。

Btw, it is not just that your tests aren't predictable, your code that uses Thread.sleep in production is going to be unpredictable for the same reasons. 顺便说一句,不仅仅是你的测试不可预测,你在生产中使用Thread.sleep的代码也会因为同样的原因而变得不可预测。 Thread.sleep(some magic number goes here) usually indicates a badly written program. Thread.sleep(some magic number goes here)通常表示编写错误的程序。

I wouldn't bother testing it. 我不打扰测试它。 100% coverage is excessive. 100%的覆盖率过高。 However, you could do it like this: 但是,你可以这样做:

@Test
public void testException() throws Exception {

    // Capture the system error stream, so that we can test that the expected exception is printed.
    ByteArrayOutputStream capturedErrors = new ByteArrayOutputStream();
    System.setErr(new PrintStream(capturedErrors));

    // Create a new thread on which to run the candidate method.
    Thread thread = new Thread() {
        @Override
        public void run() {
            SleepingHelper.sleepInMillis(Duration.ofMillis(10));
        }
    };

    // Start the second thread.
    thread.start();

    // Interrupt the second thread. (The candidate method hasn't finished yet. It takes 10 milliseconds to run.)
    thread.interrupt();

    // Wait for the thread to die (and write out the stack-trace).
    thread.join();

    // Test that the expected exception's stack trace was printed to the system error stream.
    // The output should start with the exception's name.
    String output = capturedErrors.toString();
    int lengthOfExceptionName = "java.lang.InterruptedException".length();
    assertEquals(output.substring(0, lengthOfExceptionName), "java.lang.InterruptedException");
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM