scala - 如何在集群分片测试环境中模拟演员?
问题描述
我已经设法使用 akka 和 scala 为事件源行为设置了一个测试环境,并且可以通过以下方式正确地对自包含的 Actor 运行单元测试
class CQRSActorSpec
extends ScalaTestWithActorTestKit(
EventSourcedBehaviorTestKit.config.withFallback(CQRSActorSpec.config)
)
然后创建我的测试包
private val myTestKit = EventSourcedBehaviorTestKit[Command, Event, State](system, MyActor)
并用它来发出命令
val result = myTestKit.runCommand[Response](StartJob(parameters, _))
result.reply shouldBe Done
result.event shouldBe Started(parameters)
result.state shouldBe ProcessingJob
现在我想对一个在其生命周期中调用另一个actor的actor进行单元测试,这是因为我正在使用saga模式,所以我正在测试的actor是saga的主管,并且必须调用相关方。
到目前为止,我设法做到了以下几点:
val mockParty = Behaviors.receiveMessage[Party.Command] { msg =>
val reply = msg match {
case _ => Done
}
msg.replyTo ! reply
Behaviors.same
}
ClusterSharding(system).init(Entity(Party.Key) { _ => mockParty })
这在第一次测试中运行正常,但是当我必须测试另一个时,比如说失败案例,第二次调用当然不会工作,因为集群分片中已经注册了一个实体,我无法覆盖该行为。此外,没有办法重置集群分片。
有没有人知道如何解决这个问题?还有其他我不知道的用于测试集群分片的实用程序吗?我发现文档有点缺乏。
解决方案
问题的根源是ClusterSharding(system)
在您的代码中使用它将创建真实ClusterSharding
对象,就像您说您无法控制测试一样。相反,您应该ClusterSharding
从外部传递对象,以便您可以传递它的存根/模拟实现。
这是我所说的用 Java 渲染的大纲:
让我们假设 type 的持久性 actor/event 来源行为EntityA
将创建 type 的另一个持久性 actor/event 来源行为并与之交互EntityB
。
在您的应用程序代码中的某个地方,您将ClusterSharding.init(..)
调用EntityA
:
ClusterSharding sharding = ClusterSharding.get(actorSystem); //the real stuff in the app
sharding.init(
Entity.of(
EntityA.ENTITY_TYPE_KEY,
entityContext ->
EntityA.create(
entityContext.getEntityId(),
sharding
)
)
);
注意sharding
对象是如何传递给create
方法的,EntityA
并且是与之交互的ClusterSharding
对象。EntityA
在单元测试中,不会调用此代码,相反,您可以ClusterSharding
在初始化 testKit 时注入自己的实现:
//this is in test
ClusterSharding sharding = new ClusterShardingStub(); //your stub/mock
var esbtk =
EventSourcedBehaviorTestKit.create(
testKit.system(),
EntityA.create("entityId", sharding));
所以现在在你的EntityA
实现逻辑的某个地方,你大概会调用sharding.entityRefFor(...)
来获取EntityRef<EntityBProtocol>
. 您需要做的是对您的存根/模拟进行编程以返回TestEntityRef.of(..)
实例:
TestProbe<EntityBProtocol> testProbe = TestProbe.create(testKit.system());
EntityRef<EntityBProtocol> ref = TestEntityRef.of(EntityB.ENTITY_TYPE_KEY, "entityId", testProbe.ref());
现在,任何EntityA
与 with的交互EntityB
都可以使用该TestProbe
实例进行断言。
推荐阅读
- php - 未定义的索引:QUERY_STRING php 错误导致网站速度变慢(Prestashop 1.7)
- python - 在 Python Flask 中:存储数据的合适位置是什么?
- git - Git 从活动分支创建了一个新分支,由于快进错误而无法推送
- go - Couchbase 排序选项
- jquery - jQuery包含:与长度函数完全相等
- django - Django 通过用户验证提供静态文件
- r - 带有 JQueryLayout 和 DT-table 的 Shiny-App 不起作用
- google-chrome - 使用 Chrome 或 IE 将自签名证书 (CA) 导入 Windows Certmgr.msc 不起作用
- c++ - 字母字母频率
- bots - 为什么将 LUIS 与 QnA 结合使用