Spring boot 轴突状态存储聚合测试非法状态异常

Spring boot 轴突状态存储聚合测试非法状态异常,spring-boot,axon,Spring Boot,Axon,问题:客户的技术限制迫使我在PostgreSQL中将Axon与状态存储的聚合一起使用。我尝试了一个简单的JPA实体轴突测试,得到了IllegalStateException 研究:该案例的简化项目可在 在我的测试中 fixture.givenState(MyAggregate::new) .when(command) .expectState(state -> { System.out.println(); }); 我明白了 无法检索此聚合的状态,因为

问题:客户的技术限制迫使我在PostgreSQL中将Axon与状态存储的聚合一起使用。我尝试了一个简单的JPA实体轴突测试,得到了IllegalStateException

研究:该案例的简化项目可在

在我的测试中

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

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


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

项目中缺少一些部分,无法让测试正常运行。我将尽可能简明扼要地解决这些问题:

  • 您的命令应该包含将其连接到聚合的信息
    @TargetAggregateIdentifier
    是框架提供的注释,它将某个字段与其
    @AggregateIdentifier
    对应项连接到聚合中。你可以在这里读更多。 因此,需要将UUID字段添加到
    Create
    命令中

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

  • @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);
    }
    
此测试将验证CQR的命令部分

然后,我将建议将查询部分与您的
@Aggregate
分开:然后您需要使用方法上的
@EventHandler
注释将事件处理到投影
@组件
类中,并使用
@Repository
JPA方式实现一段逻辑,该逻辑将负责以您需要的形式将信息存储到PostgreSQL
@Entity
,我相信您一定熟悉这种方式。 您可以在ref指南中找到有用的信息,该指南遵循基于此repo中的代码的查询模型的视频示例

希望一切都清楚,


科拉多。

你给我指明了正确的方向。我应该将
id
传递给命令,而不应该在命令处理程序中创建它。但是为什么我不能验证状态:
fixture.givenState
?更新了项目。在我看来,测试应该尽可能的狭窄:在我们的例子中,我们希望在某个命令上测试它,一个事件由聚合应用和处理。这也将验证我们的聚合状态。如果您想测试预期值是否发送到存储库,那么我将创建第二个测试,重点关注查询部分,或者最终创建一个端到端(集成)测试。在这种情况下,您应该考虑到从触发命令到将其写入数据库之间可能存在延迟。很抱歉,在您决定使用状态存储聚合的情况下,使用givenState测试夹具是完全可以的。这里有一个参考指南,可以帮助你,这就是安静是什么。此状态引发异常。您可以在附带的Gitlab项目中运行测试以查看。