如何在单元测试中避免Thread.sleep?

Ruf*_*ufi 11 java junit multithreading unit-testing

我们假设我有以下方法应该测试:

@Autowired
private RoutingService routingservice;

public void methodToBeTested() {
    Object objectToRoute = initializeObjectToRoute();
    if (someConditions) {
         routingService.routeInOneWay(objectToRoute);
    } else {
         routingService.routeInAnotherWay(objectToRoute);
    }
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下RoutingService,在单独的线程中运行,因此在它的构造函数中我们有以下内容:

Thread thread = new Thread(this);
thread.setDaemon(true);
thread.start();
Run Code Online (Sandbox Code Playgroud)

问题是RoutingService改变状态,objectToRoute这正是我想要检查的,但这不会立即发生,因此测试失败.但是,如果我添加Thread.sleep()然后它可以工作,但这是不好的做法,因为我知道.

Thread.sleep()在这种情况下我该如何避免?

sar*_*rah 9

我建议等待同步异步测试。例如,假设您有一个在一些线程操作后设置的结果对象,并且您想要测试它。你这样写声明:

 await()
.atMost(100, TimeUnit.SECONDS)
.untilAsserted(() -> assertNotNull(resultObject.getResult()));
Run Code Online (Sandbox Code Playgroud)

它最多等待 100 秒,或者直到断言得到满足。例如,如果 getResult() 在 0-100 秒之间返回不为 null 的内容,则执行将继续,这与 Thread.sleep 不同,无论结果是否存在,Thread.sleep 都会在给定时间内保留执行。

  • 只是想知道这里的利润是多少?除非我们只能赢得一些额外的时间,所以测试会更快一些......但它仍然类似于 thread.sleep 只是有一些语法糖 (5认同)
  • @java_newbie:来自 SonarLint 规则描述(java:S2925):`在测试中使用 Thread.sleep 通常是一个坏主意。它创建了脆弱的测试,根据环境(“在我的机器上通过!”)或负载,这些测试可能会意外失败。不要依赖计时(使用模拟)或使用 Awaitility 等库进行异步测试。 (3认同)

for*_*son 5

如果您正在测试methodToBeTested,则应该简单地进行模拟routingservice。您不应该测试任何methodToBeTested调用的方法。但是,听起来好像您想测试。RoutingService(您说“问题在于RoutingService更改了状态,objectToRoute而这正是我要检查的内容”)。要测试RoutingService方法,您应该为这些方法编写单独的单元测试。