有没有一种方法可以不使用 expectEvents 直接从测试夹具测试事件?

Is there a way to test events from the test fixture directly without using expectEvents?

我正在尝试测试聚合并想断言夹具之外的事件,甚至可能使用 Hamcrest 进行评估?

使用时间戳的示例

        fixture.given()
           .when(new UserCreateCommand("1","test@bob.com"))
           .expectEvents(new UserCreatedEvent("1","test@bob.com");

夹具让我可以轻松测试相等性,例如该命令准确地产生了这个事件,如果我想说引入一个事件创建时间的时间戳,例如

,那就没那么容易了
        fixture.given()
           .when(new UserCreateCommand("1","test@bob.com"))
           .expectEvents(new UserCreatedEvent("1","test@bob.com", LocalDateTime.now());

这种期望永远不会起作用,因为 LocalDateTime.now() 永远不会精确等于聚合中生成的时间戳。

我可以简单地将时间戳包含在命令有效负载中,但我更喜欢在聚合内部处理以确保以一致的方式生成此时间戳。

有没有办法从夹具中检索事件以独立于夹具断言,例如

   UserCreatedEvent uce = fixture.given()
           .when(new UserCreateCommand("1","test@bob.com"))
           .extractEvent(UserCreatedEvent.class)

这样我就可以使用其他断言库,例如 hamcrest:

例如

   assertThat(uce.getCreatedAt(), is(greaterThanOrEqualto(LocalDateTime.now().minusSeconds(1);

合理的问题@vcetinick!

您实际上应该能够将匹配器与 Axon 的聚合测试装置一起使用。 AggregateTestFixture 的结果验证部分提供了 expectEventsMatching(Matcher<? extends List<? super EventMessage<?>>> matcher) 方法。你可以顺便找到这个here的代码

在此 Axon 框架之上提供了一组合理的匹配器,您可以将其用于一般的消息,分组在实用程序 class Matchers 下(您可以找到 here) .

所有这些都准备就绪后,您应该可以执行以下操作:

@Test
void sampleTest() {
    FixtureConfiguration<SampleAggregate> fixture = 
        new AggregateTestFixture<>(SampleAggregate.class);
    fixture.givenNoPriorActivity()
           .when(new UserCreateCommand("1","test@bob.com"))
           .expectEventsMatching(
                   Matchers.exactSequenceOf(
                           Matchers.messageWithPayload(
                                   Matchers.matches(payload -> {
                                       // Your UserCreatedEvent validation 
                                       //  disregarding the time stamp here
                                   })
                           )
                   )
           );
}

如果您愿意,您基本上可以将任意数量的 Matchers 方法配对。

希望这能回答您@vcetinick 的问题!

尽管是旧的 post,但对于遇到相同问题的人,可以使用替代方法

fixture = new AggregateTestFixture<>(YourAggregate.class);    
fixture.registerFieldFilter(new IgnoreField(YourEvent.class, "date"));

在此示例中,YourEvent 可以是包含时间戳字段 date.

的所有事件的基础 class 的事件实现 class
@NotNull(message = "The event date cannot be null")
@Past(message = "The event date cannot be in the future")
@JsonProperty(value = EVENT_DATE_TAG, required = true)
private ZonedDateTime date;

使用这种方法,所有对 expectXXXX 测试方法的调用都会忽略 date 字段。