[英]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.