简体   繁体   English

Axon 框架:如何在单元测试中检索状态存储的聚合 id 的 id

[英]Axon framework: How to retrieve id of a state-stored aggregate id in a unit test

I am new to Axon framework and am trying to implement an application using CQRS with state-stored aggregates.我是 Axon 框架的新手,正在尝试使用带有状态存储聚合的 CQRS 来实现应用程序。 The aggregate is created via a command handling constructor that assigns a random UUID as the aggregate identifier.聚合是通过一个命令处理构造函数创建的,该构造函数分配一个随机 UUID 作为聚合标识符。

To test commands on the aggregate, I create the aggregate via a givenCommands(new CreatePlanCommand(...) call. I then want to issue the command under test, UpdatePlanNameCommand in this case, but that command needs the aggregate id that was assigned by the CreatePlanCommand executed in the test setup. Is there a way to retrieve this?为了测试聚合上的命令,我通过givenCommands(new CreatePlanCommand(...)调用创建聚合。然后我想发出被测命令,在这种情况下为UpdatePlanNameCommand ,但该命令需要由分配的聚合 ID CreatePlanCommand在测试设置中执行。有没有办法检索这个?

Example test code shown below (see question in comment on when() call):下面显示的示例测试代码(请参阅关于when()调用的评论中的问题):

@Test
public void plan_updatePlan_updatesPlanName() {
    testFixture
            .givenCommands(new CreatePlanCommand(123L, "My Test Plan", funds))
            .when(new UpdatePlanNameCommand(/* How to get aggregate id returned by CreatePlanCommand here? */, "New Name"))
            .expectSuccessfulHandlerExecution()
            .expectState(state -> {
                assertThat(state.getCompanyId(), equalTo(123L));
                assertThat(state.getName(), equalTo("New Name"));
                assertThat(state.getAvailableFunds(), equalTo(funds));
            });
}

The command handler that creates the plan is as follows:创建计划的命令处理程序如下:

@CommandHandler
public Plan(CreatePlanCommand command, PlanFundValidator planFundValidator) {
    // Use injected domain service to verify that all funds in this plan's lineup actually exist
    planFundValidator.validateFundsExist(command.getAvailableFunds());

    this.id = UUID.randomUUID();
    this.companyId = command.getCompanyId();
    this.name = command.getName();
    this.availableFunds = new HashSet<>(command.getAvailableFunds());
    apply(planCreatedEvent());
}

Update: I was able to get the test working by using .givenState(...) to create the aggregate as follows:更新:我能够通过使用.givenState(...)创建聚合来进行测试,如下所示:

@Test
public void plan_updatePlan_updatesPlanName() {
    AtomicReference<UUID> planId = new AtomicReference<>();
    testFixture
            .givenState(() -> {
                Plan plan = new Plan(new CreatePlanCommand(123L, "My Test Plan", funds), mockPlanFundValidator);
                planId.set(plan.getId());
                return plan;
            })
            .when(new UpdatePlanNameCommand(planId.get(), "New Name"))
            .expectSuccessfulHandlerExecution()
            .expectState(state -> {
                assertThat(state.getCompanyId(), equalTo(123L));
                assertThat(state.getName(), equalTo("New Name"));
                assertThat(state.getAvailableFunds(), equalTo(funds));
            });
}

but this seems overly verbose and a step backwards in terms of test readability and maintenance, so I am still curious if there is a way to accomplish this with .givenCommands(...) .但这似乎过于冗长并且在测试可读性和维护方面倒退了一步,所以我仍然很好奇是否有办法用.givenCommands(...)来完成这个。 Thank you.谢谢你。

All right, let me try to give you some info on that.好吧,让我试着给你一些关于这方面的信息。

In my opinion, the easiest way to achieve it is to move the UUID generation to another Component.在我看来,实现它的最简单方法是将 UUID 生成移动到另一个组件。 In that way, you can clearly mock it on tests.这样,您可以在测试中清楚地模拟它。

eg:例如:

@CommandHandler
public Plan(CreatePlanCommand command, PlanFundValidator planFundValidator, UUIDGenerator generator) {
    // Use injected domain service to verify that all funds in this plan's lineup actually exist
    planFundValidator.validateFundsExist(command.getAvailableFunds());

    this.id = generator.generate(); // changed this line
    this.companyId = command.getCompanyId();
    this.name = command.getName();
    this.availableFunds = new HashSet<>(command.getAvailableFunds());
    apply(planCreatedEvent());
}

Doing that, same way you mocked the PlanFundValidator , you also mock the UUIDGenerator making sure you have the needed id.这样做,与您模拟PlanFundValidator的方式相同,您还模拟了UUIDGenerator以确保您拥有所需的 id。

For the other question:对于另一个问题:

Related question: is there a way to clear any events that were raised in the given part of a test?相关问题:有没有办法清除在测试的给定部分引发的任何事件? For example, if I have a unit test for command "C" that executes commands "A" and "B" as part of its "given" to set up the test, I would like to be able to assert that command "C" (the command under test) raised the expected events and not see any events raised by commands "A" and "B" since those are not the subject of this test and have their own tests that verify they raise the expected events.例如,如果我有一个命令“C”的单元测试,它执行命令“A”和“B”作为其“给定”设置测试的一部分,我希望能够断言该命令“C” (被测命令)引发了预期的事件,但看不到命令“A”和“B”引发的任何事件,因为它们不是该测试的主题,并且有自己的测试来验证它们引发了预期的事件。

The events are not kept from test to test but if those are raised by your own test, than you have to deal with them.这些事件不会从一个测试到另一个测试,但如果这些事件是由您自己的测试引发的,那么您必须处理它们。 By the givenState you find out earlier can also help with this.通过你之前发现的givenState也可以帮助解决这个问题。 You just have to setup the state you need and fire the command/event you are testing.您只需要设置您需要的 state 并触发您正在测试的命令/事件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Axon 框架:如何使用状态存储的聚合 - Axon Framework: How to use state-stored aggregates Axon 框架:处理状态存储聚合中的数据库异常 - Axon framework: Handling database exceptions in state-stored aggregates 如何从轴突框架中的聚合成员访问聚合根状态 - How can I access aggregate root state from aggregate member in axon framework Axon - 我的聚合的唯一 ID 是否等于/与我的实体相同? - Axon - Does the unique Id of my Aggregate equal/be the same as that of my Entity? Axon 框架:聚合自动装配 Bean 在测试中抛出 NullPointerException - Axon Framework: Aggregate Autowired Bean throws NullPointerException in Test 轴突再造骨料 state 不清楚 - Axon recreating aggregate state not clear 使用段 ID 标记来自 Axon Framework MessageMonitor 的指标 - Tagging metrics from an Axon Framework MessageMonitor with the segment ID 如果ID是随机生成的,我如何测试聚合? - How Can I Test Aggregate if ID is randomly generated? Axon:事件源聚合无状态更改事件 - Axon: Eventsourced Aggregate none state changing event 如何在轴心框架的Java中不使用Spring的情况下配置处理命令和调度事件的聚合类? - How to configure aggregate class which handles command and dispatch event without using spring in java with axon framework?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM