gpt4 book ai didi

java - 使用 JUnit 对 akka actor 进行单元测试

转载 作者:行者123 更新时间:2023-11-30 03:14:56 35 4
gpt4 key购买 nike

最近我尝试为 akka actor 编写一些单元测试来测试 actor 消息流。我在测试中观察到一些奇怪的行为:

字段:

private TestActorRef<Actor> sut;
private ActorSystem system;


JavaTestKit AnotherActor;
JavaTestKit YetAnotherActor;

系统和参与者是在@Before注释的方法中创建的:

@Before
public void setup() throws ClassNotFoundException {
system = ActorSystem.apply();

AnotherActor = new JavaTestKit(system);
YetAnotherActor = new JavaTestKit(system);


Props props = MyActor.props(someReference);

this.sut = system.of(props, "MyActor"); }

下一个

@Test
public void shouldDoSth() throws Exception {
// given actor
MyActor actor = (MyActor) sut.underlyingActor();

// when
SomeMessage message = new SomeMessage(Collections.emptyList());
sut.tell(message, AnotherActor.getRef());

// then
YetAnotherActor.expectMsgClass(
FiniteDuration.apply(1, TimeUnit.SECONDS),
YetSomeMessage.class);

}

在我的代码中:

private void processMessage(SomeMessage message) {
final List<Entity> entities = message.getEntities();
if(entities.isEmpty()) {
YetAnotherActor.tell(new YetSomeMessage(), getSelf());
// return;
}

if (entities > workers.size()) {
throw new IllegalStateException("too many tasks to be started !");
}

}

基本上,有时(非常罕见)此类测试会失败(在另一个操作系统上),并且会引发 processMessage 方法的异常(由于业务逻辑而导致 IllegalStateException)。

尽管事实上也抛出了 IllegateStateException 错误并记录在堆栈跟踪中,但大多数测试都通过了 YetSomeMessage 消息被 YetAnotherActor 接收。

正如我从 akka TestActorRef 文档中假设的那样:

This special ActorRef is exclusively for use during unit testing in a single-threaded environment. Therefore, it overrides the dispatcher to CallingThreadDispatcher and sets the receiveTimeout to None. Otherwise, it acts just like a normal ActorRef. You may retrieve a reference to the underlying actor to test internal logic.

我的系统仅使用单个线程来处理参与者收到的消息。有人可以解释我为什么尽管有正确的断言,测试还是失败了吗?

当然,可以在正确的代码中发送 YetSomeMessage 后返回,但我不明白另一个线程处理如何导致测试失败。

最佳答案

由于您使用的是 TestActorRef,所以您基本上是在进行同步测试。作为一般经验法则,除非确实需要,否则不要使用 TestActorRef。那东西使用 CallingThreadDispatcher,即它将窃取调用者线程来执行 actor。因此,解决您的谜团的方法是, Actor 与您的测试在同一线程上运行,因此异常最终出现在测试线程上。

幸运的是,您的这个测试用例根本不需要 TestActorRef。您可以将 Actor 创建为普通 Actor ,一切都应该正常(即 Actor 将位于适当的单独线程上)。请尝试使用异步测试支持来完成所有操作http://doc.akka.io/docs/akka/2.4.0/scala/testing.html#Asynchronous_Integration_Testing_with_TestKit

关于java - 使用 JUnit 对 akka actor 进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32876202/

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