在 Spring 中配置 Axon 以进行集成测试
Configuring Axon in Spring for integration testing
java 和 axon 还是新手,使用 spring 和 axon 设置集成测试套件时遇到问题。
基本上,我有一些流程,其中:
- 从 command1 开始
- 转到聚合上的命令处理程序并调度 event1
- event1 由一些策略(事件侦听器)处理并生成 command2
- command2 由命令处理程序服务处理(因此没有聚合 ID),因为我需要与第三方处理一些东西
- event2 被另一个事件侦听器调度和处理,因此 command3 被调度
- command3被aggregate处理,event3被调度
我使用 axon tests 进行单元测试,效果很好。
但我想将“集成”测试添加到:
- 检查整个流程,例如:当 command1 被调度时,event1、event2、event3 被记录(实际上不关心字段,只是为了确信整个事情按预期粘合)
- 检查服务命令处理程序是否按预期方式工作“当命令 2 被调度时,然后事件 2 被记录”
我通过以下方式部分成功了 1):
package com.example.integration;
import org.axonframework.commandhandling.gateway.CommandGateway;
import org.axonframework.eventsourcing.eventstore.EmbeddedEventStore;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Arrays;
import java.util.UUID;
@RunWith(SpringRunner.class)
@SpringBootTest
@Import(IntegrationTestConfig.class)
public class ExampleIntegrationTest
{
@Autowired
private CommandGateway commandGateway;
@Autowired
private EmbeddedEventStore eventStore;
@Test
public void itShouldStoreCorrectEvents() {
var aggregateId = UUID.randomUUID().toString();
var exampleCommand = new ExampleCommand(aggregateId);
whenCommandIsDispatched(exampleCommand);
thenExpectedEventsRecorded(
Arrays.asList(
Event1.class,
Event3.class
),
aggregateId
);
}
private void whenCommandIsDispatched(Command command)
{
commandGateway.sendAndWait(command);
}
private void thenExpectedEventsDispatched(java.util.List<Class<?>> expectedEventTypes, String id)
{
var events = eventStore.readEvents(id);
while (events.hasNext()) {
Assert.assertEquals(
expectedEventTypes.get(Math.toIntExact(events.getLastSequenceNumber())),
events.next().getPayloadType()
);
}
}
}
并拥有 IntegrationConfigTest:
package com.example.library.test;
import org.axonframework.eventhandling.EventBus;
import org.axonframework.eventsourcing.eventstore.EmbeddedEventStore;
import org.axonframework.eventsourcing.eventstore.EventStorageEngine;
import org.axonframework.eventsourcing.eventstore.inmemory.InMemoryEventStorageEngine;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
@TestConfiguration
public class IntegrationTestConfig {
@Bean
@Primary
public static EventBus createSpyEventBus() {
return new EmbeddedEventStore.Builder().storageEngine(new InMemoryEventStorageEngine()).build();
}
}
很好,测试通过了,但我没有找到如何测试从服务命令处理程序(在我的示例中为 Event2)调度的事件的方法 - 此处需要聚合 ID:eventStore.readEvents(id)
。编辑:但我不想将聚合 ID 放入,因为事件未记录在任何聚合上 - 它被直接发送到 service/singleton 命令处理程序中的事件网关。
关于如何获取所有已分派的事件以便我也可以断言 Event2 已分派的任何想法?
或者我在这里遗漏了什么? :)
接收 command1 以创建聚合的初始化命令处理程序可能 return aggregateId,因此您可以获取 returned 结果并使用该 id 以供将来参考。
...
public class MyAggregate {
@CommandHandler
public static MyAggregate create(CreateCmd cmd) {
MyAggregate a = new MyAggregate();
AggregateLifecycle.apply(new CreatedEvent(UUID.randomUuid().toString());
return a;
}
}
....
String generatedId = commandGateway.sendAndWait(new CreateCmd(null));
.... // continue
如果要验证 EventStore
中的事件,可以使用 EventStore#openStream(TrackingToken)
操作。
这将打开商店中包含的事件流,从一个可定义的(读作:TrackingToken
)时间点开始。通过调整您提供的令牌,您可以选择起始位置。要构造令牌,您可以再次使用 EventStore
,它提供以下操作:
createTailToken()
- 从开头开始流
createHeadToken()
- 在最后开始流
createTokenAt(Instant dateTime)
- 在 Instant
开始播放
createTokenSince(Duration duration)
- 从 Duration
开始流式传输
鉴于您的测试范围较小,我认为 createTailToken
就可以了。
java 和 axon 还是新手,使用 spring 和 axon 设置集成测试套件时遇到问题。
基本上,我有一些流程,其中:
- 从 command1 开始
- 转到聚合上的命令处理程序并调度 event1
- event1 由一些策略(事件侦听器)处理并生成 command2
- command2 由命令处理程序服务处理(因此没有聚合 ID),因为我需要与第三方处理一些东西
- event2 被另一个事件侦听器调度和处理,因此 command3 被调度
- command3被aggregate处理,event3被调度
我使用 axon tests 进行单元测试,效果很好。
但我想将“集成”测试添加到:
- 检查整个流程,例如:当 command1 被调度时,event1、event2、event3 被记录(实际上不关心字段,只是为了确信整个事情按预期粘合)
- 检查服务命令处理程序是否按预期方式工作“当命令 2 被调度时,然后事件 2 被记录”
我通过以下方式部分成功了 1):
package com.example.integration;
import org.axonframework.commandhandling.gateway.CommandGateway;
import org.axonframework.eventsourcing.eventstore.EmbeddedEventStore;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Arrays;
import java.util.UUID;
@RunWith(SpringRunner.class)
@SpringBootTest
@Import(IntegrationTestConfig.class)
public class ExampleIntegrationTest
{
@Autowired
private CommandGateway commandGateway;
@Autowired
private EmbeddedEventStore eventStore;
@Test
public void itShouldStoreCorrectEvents() {
var aggregateId = UUID.randomUUID().toString();
var exampleCommand = new ExampleCommand(aggregateId);
whenCommandIsDispatched(exampleCommand);
thenExpectedEventsRecorded(
Arrays.asList(
Event1.class,
Event3.class
),
aggregateId
);
}
private void whenCommandIsDispatched(Command command)
{
commandGateway.sendAndWait(command);
}
private void thenExpectedEventsDispatched(java.util.List<Class<?>> expectedEventTypes, String id)
{
var events = eventStore.readEvents(id);
while (events.hasNext()) {
Assert.assertEquals(
expectedEventTypes.get(Math.toIntExact(events.getLastSequenceNumber())),
events.next().getPayloadType()
);
}
}
}
并拥有 IntegrationConfigTest:
package com.example.library.test;
import org.axonframework.eventhandling.EventBus;
import org.axonframework.eventsourcing.eventstore.EmbeddedEventStore;
import org.axonframework.eventsourcing.eventstore.EventStorageEngine;
import org.axonframework.eventsourcing.eventstore.inmemory.InMemoryEventStorageEngine;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
@TestConfiguration
public class IntegrationTestConfig {
@Bean
@Primary
public static EventBus createSpyEventBus() {
return new EmbeddedEventStore.Builder().storageEngine(new InMemoryEventStorageEngine()).build();
}
}
很好,测试通过了,但我没有找到如何测试从服务命令处理程序(在我的示例中为 Event2)调度的事件的方法 - 此处需要聚合 ID:eventStore.readEvents(id)
。编辑:但我不想将聚合 ID 放入,因为事件未记录在任何聚合上 - 它被直接发送到 service/singleton 命令处理程序中的事件网关。
关于如何获取所有已分派的事件以便我也可以断言 Event2 已分派的任何想法?
或者我在这里遗漏了什么? :)
接收 command1 以创建聚合的初始化命令处理程序可能 return aggregateId,因此您可以获取 returned 结果并使用该 id 以供将来参考。
...
public class MyAggregate {
@CommandHandler
public static MyAggregate create(CreateCmd cmd) {
MyAggregate a = new MyAggregate();
AggregateLifecycle.apply(new CreatedEvent(UUID.randomUuid().toString());
return a;
}
}
....
String generatedId = commandGateway.sendAndWait(new CreateCmd(null));
.... // continue
如果要验证 EventStore
中的事件,可以使用 EventStore#openStream(TrackingToken)
操作。
这将打开商店中包含的事件流,从一个可定义的(读作:TrackingToken
)时间点开始。通过调整您提供的令牌,您可以选择起始位置。要构造令牌,您可以再次使用 EventStore
,它提供以下操作:
createTailToken()
- 从开头开始流createHeadToken()
- 在最后开始流createTokenAt(Instant dateTime)
- 在Instant
开始播放
createTokenSince(Duration duration)
- 从Duration
开始流式传输
鉴于您的测试范围较小,我认为 createTailToken
就可以了。