【问题标题】:How to test a method using sleep() with Java?如何在 Java 中使用 sleep() 测试方法?
【发布时间】:2016-01-23 21:17:29
【问题描述】:

我有以下方法,我正在努力获得 100% 的代码覆盖率。

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

问题是如何强制Thread.sleep 抛出异常?

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

【问题讨论】:

  • 专注于 100% 的覆盖率是一种妄想。除了增加覆盖率之外,测试此方法不会为您提供任何进一步的补充。测试这种方法的目的是什么?除了 Thread.sleep 正在工作之外,没有其他的。很明显,由于您对断言这是您不想编写的测试的问题!
  • 我同意,但我正在开展一个我们强制 100% 代码覆盖率的项目。
  • 如果这是项目义务,我将创建一个没有任何断言的测试 - 你得到 100% 并且测试不会失败......或AssertEquals(true, true)
  • 有道理。我会做这样的事情。

标签: java junit


【解决方案1】:

您需要从另一个线程中断它。例如:

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

【讨论】:

  • 谢谢!这有帮助,但你会在测试中断言什么?
  • 我不知道,这取决于您要验证的行为或合同类型。你想具体测试什么?那个jdk正确地实现了sleep()?测试不是您编写的函数的行为通常不是一个好主意
【解决方案2】:

您实际上不需要中断线程。可以使用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");
        }

    }

【讨论】:

  • FTR 这在新的 Mockito 静态模拟中不起作用... org.mockito.exceptions.base.MockitoException:无法模拟 java.lang.Thread 的静态方法以避免干扰类加载导致无限循环
【解决方案3】:

你不测试它,因为你不能断言它的结果,你不能断言它是因为Thread.sleep在这段时间内不准确或保证睡眠,测试结果会与跑跑跑。

Mocking 是一个更好的选择。

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

【讨论】:

    【解决方案4】:

    我不会费心去测试它。 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");
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-11-21
      • 1970-01-01
      • 2015-01-30
      • 1970-01-01
      • 1970-01-01
      • 2021-02-17
      • 2015-03-27
      相关资源
      最近更新 更多