如何在 Java 中使用 sleep() 测试方法?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34968968/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 23:35:48  来源:igfitidea点击:

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

javajunit

提问by Paul Fournel

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.sleepto 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.

编辑:因为它被标记为重复,我仍然想知道我会在测试中断言什么?另一个问题更笼统。

回答by Dima

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;

回答by Nir Levy

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");
        }

    }

回答by Sleiman Jneidi

You don't test it, because you can't assert its results, and you can't assert it because Thread.sleepis not accurate or guaranteed to sleep for this duration of time, and the test results will differ from run to run.

你不测试它,因为你不能断言它的结果,你不能断言它因为Thread.sleep不准确或保证在这段时间内休眠,并且测试结果会因运行而异。

Mockingis a better option here.

Mocking这里是一个更好的选择。

Btw, it is not just that your tests aren't predictable, your code that uses Thread.sleepin production is going to be unpredictable for the same reasons. Thread.sleep(some magic number goes here)usually indicates a badly written program.

顺便说一句,不仅仅是您的测试不可预测,Thread.sleep出于同样的原因,您在生产中使用的代码也将是不可预测的。Thread.sleep(some magic number goes here)通常表示程序编写得不好。

回答by whistling_marmot

I wouldn't bother testing it. 100% coverage is excessive. However, you could do it like this:

我不会费心去测试它。100% 覆盖率过高。但是,您可以这样做:

@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");
}