在TDD和DDD中,如何处理假货中的只读属性?

Joh*_*ohn 5 tdd asp.net-mvc domain-driven-design nerddinner

创建假货时如何处理只读字段?

背景

我正处于使用ASP.Net MVC的初学阶段,我正在使用Steven Sanderson的体育用品店和Scott Gu的书呆子晚餐作为例子.我刚刚遇到的一个小问题是如何在做假货时使用只读属性.我正在使用LINQToSQL.

我的界面是:

public interface IPersonRespository
{   
    Person GetPerson(int id);
}
Run Code Online (Sandbox Code Playgroud)

而我的假装变成了

public class FakePersonRepository
{
    public Person GetPerson(int id)
    {
        return new Person {id="EMP12345", name="John Doe", age=47, ssn=123-45-6789, totalDrWhoEpisodesWatched=42};
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的问题.字段id,ssn和totalDrWhoEpisodesWatched是只读的,因此上面的代码实际上不起作用.但是,我不知道如何创建假新人并设置只读属性.我确信有一个解决方案,但我在搜索中还没有遇到过它.

更新:继承+属性隐藏为潜在的解决方案?

我还没有决定解决这个问题.我不喜欢为了创造假货而修改我的Domain类的概念.对我来说,为了进行测试而向域类添加标记是一种额外的耦合形式 - 与测试的实现相结合.我现在正在研究另一种可能性,即创建一个继承自Person的FakePerson类,但使用新的读写属性隐藏属性.

public class FakePerson: Person
{
    public new int age { get; set; }
    public new string ssn { get; set; }
    public new int totalDrWhoEpisodesWatched { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

到目前为止,这个解决方案就是我的倾向.它确实打破了Liskov替换原则,但是这并没有在测试项目中给我带来太多麻烦.我很高兴听到任何批评和/或反馈作为解决方案.

获奖者:模拟框架

Moq似乎完成了这项工作.事实上,我通过继承隐藏属性的最后一个解决方案确实有效,但是通过使用Moq,我获得了一组更易于维护的标准化功能.我假设其他模拟框架具有此功能,但我没有检查.据说Moq开始模拟写作更直接,我现在肯定是这样.

mvr*_*mvr 6

考虑模拟测试中的Person类型.使用Moq的示例:

var mock = new Mock<Person>();
mock.SetupGet(p => p.id).Returns("EMP12345");
mock.SetupGet(p => p.ssn).Returns("123-45-6789");
mock.SetupGet(p => p.totalDrWhoEpisodesWatched).Returns(42);
return mock.Object;
Run Code Online (Sandbox Code Playgroud)

否则,请尝试了解LINQ to SQL如何设置这些只读属性.

编辑:如果您尝试上述操作并且Moq ArgumentExceptionSetupGet调用中抛出一条消息"无法覆盖的成员上的无效设置:p => p.id",则需要将该属性标记为虚拟.对于要覆盖其getter的每个属性,都需要执行此操作.

在LINQ to SQL中,可以通过选择属性在OR设计器中完成,然后在Properties窗口中将Inheritance Modifier设置为virtual.