gpt4 book ai didi

java - 如何对暂停执行的代码进行单元测试而不将其抽象出来?

转载 作者:行者123 更新时间:2023-11-30 03:31:51 25 4
gpt4 key购买 nike

我必须对一个暂停执行的方法进行单元测试(定期做一些工作):

void m() {
do {
doSomeWork();
Thread.sleep(1000);
} while (condition);
}

我必须测试的是多个 while 循环执行并检查 doSomeWork() 是否已正确完成。所以目前我的测试如下所示:

1) 在新线程中开始执行 m()。

2)在主线程中:Thread.sleep(1000 + 200);

3) 在主线程中断言工作已正确完成。

4)在主线程中:Thread.sleep(1000 + 200);

5) 在主线程中断言工作已正确完成。

6) 再一次4和5

问题是不同机器上的 doSomeWork() 花费的时间不同,并且很难在测试中找到一个好的等待值。

我看到解决这种情况的常见方法是抽象出 sleep 时间,并且在测试代码中不要等待: C# Unit Testing - Thread.Sleep(x) - How to Mock the System Clock

但我确实必须验证实现是否正在等待。

对于如何为这种情况编写健壮的单元测试代码,您有什么建议吗?它还可能涉及 m() 方法的重构。

最佳答案

处理此类问题的常见方法是使用对象等待/通知方法。这也将有助于使方法 m() 在其他上下文中更可用。所以像这样的实现:

void m() {
do {
doSomeWork();
Thread.sleep(1000);
synchronized (this) {
this.notifyAll();
}
} while (condition);
}

然后在您的测试类中您可以执行以下操作:

...
synchronized (obj) {
obj.wait(10000);
}

等待中的10000只是用于该类的超时。这可以防止永远 hibernate 的 m 重构(或等效错误)导致测试超时。

当然,这个建议需要一些对象用于互斥体。我为 m 选择了类本身,但可以使用任何对象。有时我只是为了这种类型的使用而创建一个对象:Object mutex = new Object()

如果您需要确保工作和 sleep 是否成功,那么您还可以使用 AtomicInteger 作为计数器:

AtomicInteger counter = new AtomicInteger(0);
void m() {
do {
doSomeWork();
Thread.sleep(1000);
counter.incrementAndGet()
synchronized (counter) {
counter.notifyAll();
}
} while (condition);
}

然后在您的测试类中您可以执行以下操作(为简单起见,缺少适当的方法):

...
synchronized (obj.counter) {
obj.counter.wait(10000);
}
assert(obj.counter.get() > 0);

关于java - 如何对暂停执行的代码进行单元测试而不将其抽象出来?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28841469/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com