【发布时间】:2019-01-30 17:54:10
【问题描述】:
Java 8 和 Akka (Java API) 2.12:2.5.16 在这里。我有以下消息:
public class SomeMessage {
private int anotherNum;
public SomeMessage(int anotherNum) {
this.anotherNum = anotherNum;
}
public int getAnotherNum() {
return anotherNum;
}
public void setAnotherNum(int anotherNum) {
this.anotherNum = anotherNum;
}
}
还有以下演员:
public class TestActor extends AbstractActor {
private Integer number;
public TestActor(Integer number) {
this.number = number;
}
@Override
public Receive createReceive() {
return receiveBuilder()
.matchAny(message -> {
if (message instanceof SomeMessage) {
SomeMessage someMessage = (SomeMessage) message;
System.out.println("someMessage contains = " + someMessage.getAnotherNum());
someMessage.setAnotherNum(number);
}
}).build();
}
}
还有下面的单元测试:
@RunWith(MockitoJUnitRunner.class)
public class TestActorTest {
static ActorSystem actorSystem;
@BeforeClass
public static void setup() {
actorSystem = ActorSystem.create();
}
@AfterClass
public static void teardown() {
TestKit.shutdownActorSystem(actorSystem, Duration.create("10 seconds"), true);
actorSystem = null;
}
@Test
public void should_alter_some_message() {
// given
ActorRef testActor = actorSystem.actorOf(Props.create(TestActor.class, 10), "test.actor");
SomeMessage someMessage = new SomeMessage(5);
// when
testActor.tell(someMessage, ActorRef.noSender());
// then
assertEquals(10, someMessage.getAnotherNum());
}
}
所以我要验证的是TestActor 确实收到了SomeMessage 并且它改变了它的内部状态。
当我运行这个单元测试时,它失败了,好像演员从来没有收到过消息:
java.lang.AssertionError:
Expected :10
Actual :5
<Click to see difference>
at org.junit.Assert.fail(Assert.java:88)
at org.junit.Assert.failNotEquals(Assert.java:834)
at org.junit.Assert.assertEquals(Assert.java:645)
<rest of trace omitted for brevity>
[INFO] [01/30/2019 12:50:26.780] [default-akka.actor.default-dispatcher-2] [akka://default/user/test.actor] Message [myapp.actors.core.SomeMessage] without sender to Actor[akka://default/user/test.actor#2008219661] was not delivered. [1] dead letters encountered. If this is not an expected behavior, then [Actor[akka://default/user/test.actor#2008219661]] may have terminated unexpectedly, This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.
但是当我修改测试方法并将Thread.sleep(5000) 引入其中时(在tell(...) 之后),它以出色的成绩通过:
@Test
public void should_alter_some_message() throws InterruptedException {
// given
ActorRef testActor = actorSystem.actorOf(Props.create(TestActor.class, null, 10), "test.actor");
SomeMessage someMessage = new SomeMessage(5);
// when
testActor.tell(someMessage, ActorRef.noSender());
Thread.sleep(5000);
// then
assertEquals(10, someMessage.getAnotherNum());
}
这是怎么回事?! 显然我不希望我的演员测试到处都是sleeps,那么我在这里做错了什么,解决方法是什么?提前致谢!
【问题讨论】:
标签: java multithreading junit akka akka-testkit