如果ID是随机生成的,我该如何测试汇总?

时间:2020-02-02 17:29:12

标签: java domain-driven-design axon

这可能更多是设计问题,但是我有一个通过命令生成的聚合成员,并且需要能够测试在运行命令后是否生成了事件。

但是,我没有发现在TestFixture框架中的事件的一个字段上进行anyString匹配的任何明显方法。

在创建汇总时生成ID是“不好的做法”吗? ID应该在集合之外生成吗?

@AggregateMember(eventForwardingMode = ForwardMatchingInstances.class)
private List<TimeCardEntry> timeCardEntries = new ArrayList<>();

data class ClockInCommand(@TargetAggregateIdentifier val employeeName: String)

@CommandHandler
public TimeCard(ClockInCommand cmd) {
  apply(new ClockInEvent(cmd.getEmployeeName(),
      GenericEventMessage.clock.instant(),
      UUID.randomUUID().toString()));


@EventSourcingHandler
public void on(ClockInEvent event) {
  this.employeeName = event.getEmployeeName();
  timeCardEntries.add(new TimeCardEntry(event.getTimeCardEntryId(), event.getTime()));
}

@Data
public class TimeCardEntry {

  @EntityId
  private final String timeCardEntryId;
  private final Instant clockInTime;
  private Instant clockOutTime;

  @EventSourcingHandler
  public void on(ClockOutEvent event) {
    this.clockOutTime = event.getTime();
  }

  private boolean isClockedIn() {
    return clockOutTime != null;
  }
}

@ParameterizedTest
@MethodSource(value = "randomEmployeeName")
void testClockInCommand(String employeeName) {
    testFixture.givenNoPriorActivity()
            .when(new ClockInCommand(employeeName))
            .expectEvents(new ClockInEvent(employeeName, testFixture.currentTime(), "Any-String-Works"));
}

1 个答案:

答案 0 :(得分:4)

在创建汇总时生成ID是“不好的做法”吗? ID应该在集合之外生成吗?

随机数非常类似于时钟-它们是共享的可变状态的一种形式。换句话说,它们是imperative shell的关注点,而不是功能核心的关注点。

这通常对您的域模型意味着随机性作为参数传递,而不是由聚合本身产生。这可能意味着将ID生成器传递到域模型,甚至在应用程序中生成ID并传递生成的标识符as a value

因此,在我们的单元测试中,我们将目标应用程序提供的随机生成器替换为测试提供的“随机”生成器-因为测试控制生成器,所以使用的标识符具有确定性,因此您可以轻松解决它。

如果您不愿意将随机生成器作为域模型api的一部分,则另一种选择是将其作为测试接口的一部分公开。

// We don't necessarily worry about testing this version, it is "too simple to break"
void doSomethingCool(...) {
    doSomethingCool(ID.new, ...);
}

// Unit tests measure this function instead, which is easier to test and has
// all of the complicated logic
void doSomethingCool(ID id, ...) {
    // ...
}
相关问题