【问题标题】:Axon State-Stored Aggregate Test IllegalStateExceptionAxon 状态存储聚合测试 IllegalStateException
【发布时间】:2020-07-23 08:00:37
【问题描述】:

问题:客户技术限制迫使我将 Axon 与 PostgreSQL 中的状态存储聚合一起使用。我尝试了一个简单的 JPA-Entity Axon-Test 并得到 IllegalStateException。

研究:关于该案例的简化项目可在https://gitlab.com/ZonZonZon/simple-axon.git 获得

在我的测试中

fixture.givenState(MyAggregate::new)
    .when(command)
    .expectState(state -> {
      System.out.println();
    });

我明白了

无法检索此聚合的状态,因为它已在回滚的工作单元中进行了修改 java.lang.IllegalStateException:无法检索此聚合的状态,因为它已在回滚的工作单元中进行了修改 在 org.axonframework.common.Assert.state(Assert.java:44)

问题:如何使用 Axon 测试聚合状态并避免错误?

【问题讨论】:

    标签: spring-boot axon


    【解决方案1】:

    您的项目中缺少一些让测试正常运行的部分。我会尽量简洁地解决它们:

    • 您的命令应包含将其连接到聚合的信息。 @TargetAggregateIdentifier 是框架提供的注释,它将某个字段与其@AggregateIdentifier 对应项连接到您的聚合中。你可以在这里阅读更多内容https://docs.axoniq.io/reference-guide/implementing-domain-logic/command-handling/aggregate#handling-commands-in-an-aggregate。 也就是说,需要将 UUID 字段添加到您的 Create 命令中。

    • 然后,此信息将被传递到 Created 事件:事件被存储并且可以通过重播或聚合重新水化(在客户端重新启动时)进行处理。 (这些)是我们信息的真实来源。

    • @EventSourcingHandler 注释方法将负责应用事件并更新@Aggregate

      public void on(Created event) {
           uuid = event.getUuid();
           login = event.getLogin();
           password = event.getPassword();
           token = event.getToken();
      }
      
    • 测试将如下所示

      public void a_VideochatAccount_Created_ToHaveData() {
      
         Create command = Create.builder()
                                .uuid(UUID.randomUUID())
                                .login("123")
                                .password("333")
                                .token("d00a1f49-9e37-4976-83ae-114726938c73")
                                .build();
      
         Created expectedEvent = Created.builder()
                                       .uuid(command.getUuid())
                                       .login(command.getLogin())
                                       .password(command.getPassword())
                                       .token(command.getToken())
                                       .build();
      
         fixture.givenNoPriorActivity()
                .when(command)
                .expectEvents(expectedEvent);
      }
      

    此测试将验证您的 CQRS 的命令部分

    然后我会建议将 Query Part 与您的 @Aggregate 分开:然后您需要处理带有 @EventHandler 注释的事件到 Projection @Component 类的方法中,并且使用@Repository JPA 方式,我相信你很熟悉这种逻辑,它将负责以你需要的形式将信息存储到 PostgreSQL @Entity 中。 您可以在参考指南https://docs.axoniq.io/reference-guide/implementing-domain-logic/event-handling 上找到有用的信息,根据您可以在此 repo https://github.com/AxonIQ/food-ordering-demo/tree/master 中找到的代码在查询模型上的视频示例之后找到有用的信息

    希望一切都清楚,

    科拉多。

    【讨论】:

    • You.ve 为我指明了正确的方向。我应该将id 传递给命令并且不应该在命令处理程序中创建它。但是为什么我不能验证状态:fixture.givenState?更新了项目。
    • 在我看来,测试应该尽可能窄:在我们的例子中,我们想测试在某个命令下,聚合应用和处理一个事件。这也将验证我们的聚合状态。如果您想测试预期值是否已发送到您的存储库,那么我将创建第二个测试,该测试将专注于查询部分,或者最终是一个端到端(集成)测试。在这种情况下,您应该考虑到从触发命令到将其写入数据库之间可能存在延迟。
    • 对不起,在您决定使用状态存储聚合的情况下,使用 givenState 测试夹具非常好。这是一篇可以帮助你的参考指南docs.axoniq.io/reference-guide/implementing-domain-logic/…
    • 这就是问题所在。此状态引发异常。您可以在随附的 Gitlab 项目中运行测试以查看。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-28
    相关资源
    最近更新 更多