首页 文章

akka持久化演员测试事件生成

提问于
浏览
0

通过CQRS命令的定义可以/应该验证并且最终甚至拒绝(如果验证没有通过) . 作为我的命令验证的一部分,我检查是否真的需要状态转换 . 因此,让我们举一个简单的虚拟示例:actor处于状态A.命令被发送到actor以转移到状态B.命令被验证并且在结束时生成事件 StateBUpdated . 然后发送完全相同的命令以转移到状态B.再次命令得到验证,并且在验证期间确定不会生成任何事件(因为我们已经处于状态B)并且只是响应该命令被处理并且一切都是好 . 这是一种幂等的东西 .

不过,我很难(单位)测试这个 . 持久性actor的常用单元测试看起来像向actor发送命令然后重新启动actor并检查状态是否持久化 . 我想测试是否向actor发送命令以检查生成了多少事件 . 怎么做?

谢谢

2 回答

  • 0

    我们在开发基于akka持久性的内部CQRS框架时遇到了这个问题 . 我们的解决方案是使用持久性查询(https://doc.akka.io/docs/akka/2.5/scala/persistence-query.html) . 如果您还没有使用它,它是日志插件可以选择实现的查询接口,并且可以用作CQRS系统中的读取端 .

    为了您的测试目的,该方法将是eventsByPersistenceId,它将为您提供akka流源,其中包含actor所持有的所有事件 . 源可以折叠成一系列事件,例如:

    public CompletableFuture<List<Message<?>>> getEventsForIdAsync(String id, FiniteDuration readTimeout) {
      return ((EventsByPersistenceIdQuery)readJournal).eventsByPersistenceId(id, 0L, Long.MAX_VALUE)
          .takeWithin(readTimeout)
          .map(eventEnvelope -> (Message<?>)eventEnvelope.event())
          .<List<Message<?>>>runFold(
              new ArrayList<Message<?>>(),
              (list, event) -> {
                list.add(event);
                return list;
              }, materializer)
          .toCompletableFuture();
    }
    

    很抱歉,如果上面看起来很臃肿,我们使用Java,所以如果你习惯了Scala,那确实很难看 . 获取readJournal非常简单:

    ReadJournal readJournal = PersistenceQuery.lookup().get(actorSystem)
        .getReadJournalFor(InMemoryReadJournal.class, InMemoryReadJournal.Identifier())
    

    您可以看到我们使用akka.persistence.inmemory插件,因为它最适合测试,但任何实现持久性查询API的插件都可以使用 .

    我们实际上在我们的框架中制作了类似BDD的测试API,所以典型的测试看起来像这样:

    fixture
      .given("ID1", event(new AccountCreated("ID1", "John Smith")))
      .when(command(new AddAmount("ID1", 2.0)))
      .then("ID1", eventApplied(new AmountAdded("ID1", 2.0)))
      .test();
    

    如您所见,我们还处理在给定子句中设置先前事件以及可能处理多个persistenceIds(我们使用ClusterSharding)的情况 .

  • 1

    从你的描述看起来你需要嘲笑你的持久性,或者至少能够轻松地访问它的状态 . 我能找到两个可以做到这一点的项目:

    akka-persistence-mock设计用于测试,但未积极开发 .

    akka-persistence-inmemory

    在测试持久性actor,持久性FSM和akka集群时非常有用 .

    我会推荐后者,因为它提供了从期刊中检索所有消息的可能性 .

相关问题