等待一个Actor退出()

13

如何等待Scala Actor完成exit()? 我在单元测试中设置了两个Actor,并发送了一些消息以启动它们。 它们之间相互发送几条消息,最终都会调用exit()。 我如何使我的单元测试等待两个Actor完成后才通过?

2个回答

7

如果您事先知道参与方之间的消息交换次数,您可以使用 java.util.concurrent.CountDownLatch 来跟踪消息计数。在参与方中,在每处理一条消息后执行以下操作:

latch.countDown()

在你的主线程中执行以下操作:
latch.await()

这将使您的主线程等待,直到门闩计数降至零。
如果您不知道消息数量,但有一个指示完成的条件,则可以使用java.util.concurrent.locks.Condition。在演员中,当满足您的条件时,请执行以下操作:
if (conditionSatisfied)
  condition.signal()

在你的主线程中执行:
while (!conditionSatisfied)
 condition.await()

使其等待直到条件得到满足。

具体详情请参阅CountDownLatchCondition的javadoc。

使用Condition的示例,请参阅此Gist


1
我可以在退出之前调用countDown(),并且只计数到1。不过这似乎是多余的,因为这两个方法总是会一起被调用。 - Craig P. Motlin
我不明白。您希望主线程等待演员完成,对吗?这就是await()调用所做的事情。 - Abhinav Sarkar
这意味着我必须为生产代码(即演员)纯粹为了进行 JUnit 测试(等待演员)添加一个锁存器或条件。 - Craig P. Motlin
1
用带有阀门或条件的“单元测试”委托演员包装您的“生产”演员。 - Abhinav Sarkar
今天我遇到了这个问题,我使用了一个CountDownLatch,在actor中的“exit”之前释放。在actor主体外面(我使用的是“actor{...}”,而不是继承),我进行等待。虽然Actor对象中没有API来实现这一点,但这很容易做到。我这样做的原因是什么?外部调用是顺序的,但在某个函数内部,我使用并行处理(actors)。在从函数返回之前,我需要确保所有工作都已完成。 - akauppi

2
在 Specs 中,您可以使用最终匹配器。如果您知道您的演员或任何实体(比如持久化存储)的最终状态,您可以强制测试等待,直到切换到该状态为止。
<entity state> must eventually(10, 1.second)(be(<state>)) // there will be 10 retires every second, and if the state will be different, exception is thrown

1
那将使单元测试需要大约0.1秒才能运行,这太慢了。 - Craig P. Motlin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接