【发布时间】:2022-01-07 17:04:04
【问题描述】:
让我们考虑下面的例子:
internal class Meeting
{
public int Id { get; set; }
}
internal class DailyRoomReservation
{
private ISet<Meeting> _meetings { get; set; } = new HashSet<Meeting>();
internal void ScheduleMeeting(Meeting meeting)
{
if (_meetings.Contains(meeting)) throw new InvalidOperationException();
_meetings.Add(meeting);
}
}
假设DailyRoomReservation 是我的聚合根(为了简单起见,我故意省略了大部分业务逻辑),我应该如何测试它?仅公开聚合的命令方法(CQS 术语)是已知的良好做法,尤其是在大图使用 CQRS 时。此外,我没有公开_meetings 属性的业务需要(测试目的当然不是这样做的好理由)。我写了以下测试:
[Test]
internal void ScheduleNewMeeting_ShouldSucceed()
{
var uniqueMeeting = new Meeting() { Id = 1};
var dailyRoomReservation = new DailyRoomReservation();
dailyRoomReservation.ScheduleMeeting(uniqueMeeting);
}
[Test]
internal void ScheduleSameMeetingTwice_ShouldFail()
{
var meeting = new Meeting() { Id = 1};
var dailyRoomReservation = new DailyRoomReservation();
dailyRoomReservation.ScheduleMeeting(meeting);
Action scheduleMeeting = () => dailyRoomReservation.ScheduleMeeting(meeting);
scheduleMeeting.Should().ThrowExactly<InvalidOperationException>();
}
而且它们工作得很好,但是我仍然无法验证是否真的添加了会议。如何改进我的方法?
【问题讨论】:
-
即使没有暴露,
_meeting也必须有一些效果,而不仅仅是存在。它是干什么用的?这能提供一种测试方法吗?还是可以将其公开为只读集合? -
是的,我的系统多次读取它,但所有这些操作的入口点都是查询(正如我所提到的,我试图在架构级别应用 CQRS)。可以通过发送添加会议的命令进行测试,然后通过查询检索保存的数据。但它只能在低级别的黑盒方法中实现(因此没有经过单元测试)。
-
请问您是如何将聚合状态暴露给持久层的?
-
曝光是什么意思?我如何允许 ORM 读取它的状态?如果是 - 我使用实体框架和字符串导航属性:
builder.Entity<DailyRoomReservation>().HasMany("_meetings")
标签: c# .net unit-testing domain-driven-design aggregateroot