这可能更多是设计问题,但是我有一个通过命令生成的聚合成员,并且需要能够测试在运行命令后是否生成了事件。
但是,我没有发现在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"));
}
答案 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, ...) {
// ...
}