【问题标题】:How to stop main method calling sleep() method, when testing it with Junit?使用 Junit 进行测试时,如何停止调用 sleep() 方法的主方法?
【发布时间】:2020-08-08 13:08:55
【问题描述】:

我正在测试一个包含 sleep 的方法。什么是停止调用 sleep() 的方法,因为它会使测试变慢??

  public void fun(Integer timeToWait) {
    TimeLimiter timeLimiter = new SimpleTimeLimiter();
    try {
      timeLimiter.callWithTimeout(() -> {
        while (true) {
          if (avrageIsAboveThanDesired) {
            return true;
          }
          sleep(ofSeconds(REQUEST_STATUS_CHECK_INTERVAL));
        }
      }, timeToWait, TimeUnit.MINUTES, true);
    } catch (UncheckedTimeoutException e) {
      logger.error("Timed out waiting Instances to be in Running State", e);
    } catch (WingsException e) {
      throw e;
    } catch (Exception e) {
      throw new InvalidRequestException("Error while waiting Instaces to be in Running State", e);
    }
  }

【问题讨论】:

  • 调用像 sleep() 这样的“低级”方法本身就是一个问题。例如,请参阅medium.com/my-random-thoughts-in-software-engineering/…。含义:不要只是去选择第一个听起来有帮助的实用程序类(如番石榴 TimeLimiter)。而是了解这些东西在做什么......

标签: java unit-testing junit mockito thread-sleep


【解决方案1】:

没有简单的方法可以做到这一点。您有多种选择。

最简单的方法是使REQUEST_STATUS_CHECK_INTERVAL 可配置并在测试中将其配置为0。它可以是被测试类的属性。

sleep(ofSeconds(getSleepInternval()));

在测试中会调用

testedObject.setSleepInterval(0);

第二种选择是将睡眠调用提取到它自己的可以模拟的类中。

class Sleeper {
   void sleep(long milisecs) {
     Thread.sleep(milisecs);
   }
}

在你的课堂上你会有

private Sleeper sleeper = new Sleeper(); //nd it's setter, or dependency injection

在函数中

sleeper.sleep(ofSeconds(REQUEST_STATUS_CHECK_INTERVAL));

你可以做的测试

Sleeper mockedSleeper = Mockito.mock(Sleeper.class);
testedObject.setSleeper(mockedSleeper);

【讨论】:

  • 好点,但添加 setter() 始终是一个糟糕的选择(因为这会阻止您将字段设为 final)。所以:可以使用 Mockitos @InjectMocks 注释......或者添加一个构造函数来获取所需的对象,以允许“手动”注入。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-30
  • 1970-01-01
  • 1970-01-01
  • 2019-12-15
相关资源
最近更新 更多