C# 您应该测试它,因为应用程序代码中的任何代码都会使该模型处于不一致的状态

C# 您应该测试它,因为应用程序代码中的任何代码都会使该模型处于不一致的状态,c#,unit-testing,domain-driven-design,moq,C#,Unit Testing,Domain Driven Design,Moq,测试域实体时,应测试行为。和行为是使用实体中的方法添加的。最简单的入门方法是将所有属性设置器设置为私有 public User { Address _address; public User(int id, Address address) { //assign } public int Id {get;private set;} public bool IsAddressSame(Address address) { if (addres

测试域实体时,应测试行为。和行为是使用实体中的方法添加的。最简单的入门方法是将所有属性设置器设置为私有

public User
{
  Address _address;

  public User(int id, Address address)
  {
     //assign
  }

  public int Id {get;private set;}

  public bool IsAddressSame(Address address)
  {
      if (address == null)
          throw new ArgumentNullException("address");

      return address.Equals(_address);
  }

  public void Move(Address newAddress)
  {
      if (address == null)
          throw new ArgumentNullException("address");

      var old = _address;
      _address = newAddress;
      DomainEvent.Publish(UserMoved(_old, newAddress);
  }  
}
现在可以测试address方法的行为

如果不创建MyClass1,我如何测试MyClass1,将其与MyClass2隔离 自己的接口,然后使用moq在测试中创建一个实现 笨蛋

不要为域实体创建接口。接口的目的是创建抽象,以从应用程序的其他部分删除依赖项。将领域模型抽象出来有什么意义?在DDD中,它是应用程序的核心。没有它你就没有

由于状态现在受到保护,您知道每个实体都有一个正确的状态。因此,您不需要将用户与地址隔离。相反,只需为您创建的方法编写测试

更新以回答评论


“当您测试域实体时,您应该测试行为”看起来不错,但在TDD中,我必须在创建实现之前和之后编写测试,因此如果我想要一个具有Class2属性的Class1,我首先必须测试我是否具有此属性


不。在TDD中,您还应该测试行为。依赖关系由行为驱动,反之亦然

我的意思是,除非你有一个口头要求,要求对一个用户地址做一些事情,否则根本没有办法真正知道用户和地址之间有关系

根据这个要求,您应该在用户类上测试该方法,而不是直接访问地址

我没有理由为我的项目创建接口,但在这一点上,我很难创建测试

很多开始测试的人倾向于使用它有自己的优点(可以在一行代码中创建实例)和缺点(它们没有应该指定的行为,有时很难设置正确的行为)

我在整理测试数据时遇到了同样的问题,但我找到了几种解决方案

第一个解决方案是模式

var myClass1 = ClassBuilder.GetClass1();
var myClass2 = ClassBuilder.GetClass2();
var myClass1 = new Class1Builder.Build();
var myClass2 = new Class2Builder.WithSomeProprty().Build();
方法
GetClass1()
GetClass2()
封装创建逻辑

第二个是模式

var myClass1 = ClassBuilder.GetClass1();
var myClass2 = ClassBuilder.GetClass2();
var myClass1 = new Class1Builder.Build();
var myClass2 = new Class2Builder.WithSomeProprty().Build();
classbuilder
Class2Builder
实现允许我们用足够清晰的名称链接方法

有两篇关于和模式的老文章

我没有使用过,但有些人使用以下框架来构建测试数据:


不要仅仅因为在测试中需要接口就创建接口。好吧,塔特的观点是正确的,我也同意。在这种情况下,我将使用mr100虚拟财产。在TDD iam testng中,我的对象有一个Class2属性。我使用NHibernte,所有对象属性和方法都是虚拟的,因此这可以解决,但更好的选择是在应用程序中进行依赖项注入。如果您决定为不同的ORM更改NHibernate,请考虑会发生什么。如果您将所有内容都与接口分离,那么此更改相当简单。我在引导程序中使用ninject构建了所有内容,在数据访问层之外,我没有提到nhibernate,只提到存储库和UoW接口。但DI如何进入域层类?“当您测试域实体时,您应该测试行为”看起来不错,但在TDD中,我必须在创建实现之前和之后编写测试,所以如果我想要一个具有Class2属性的Class1,我首先必须测试我是否具有此属性No。在TDD中,您还应该测试行为。依赖关系是由行为驱动的,而不是由行为驱动的。一个简单的例子:用户可以添加、编辑和删除社会和活动;每项活动都必须有一个相关的社会。没有推荐人我怎么办?顺便说一句,没有争议,我真的很感兴趣的一个替代路线,我通常的想法​​把物体连在一起这对我来说还是太抽象了。您能添加一个具体的示例来说明对象之间的关系吗?对于编辑2:您不应该引用其他AR。您可以使用Id/VO。当您需要实例时,您可以根据Id获取它。希望图像可以提供更多帮助。如上所述,每个对象都可以单独存在(可能不包括促进,这是一个多方面的关系),只是为了强调这个概念,表示的所有实体都必须允许CRUD操作,因为用户要求在管理主表之外的所有服务表时拥有完全的自由。如果CRUD是一项要求,则不应使用DDD。DDD中的一个重要内容是保护域模型,它不能很好地与CRUD一起工作。我目前在测试中使用moq和AF,我甚至尝试使用fluent factory(与开始和结束类似,但我甚至需要一些reuired字段,所以我需要一个order fluent,可以在这里找到示例)对于创建我的域对象,请停止,因为它增加了很多复杂性:构造函数和属性在我的团队中运行良好。但不知道在外部类(工厂、母类或构建器)中创建对象如何删除对象之间的依赖关系。在您的示例中,若收件人有一些错误,则声明测试将失败:我希望避免这种情况,即外部类不会删除依赖项。它们简化了测试中使用的域对象的创建。与其建立模拟,不如建立真实的实例。有时甚至更容易,因为建筑商/工厂可以广泛地重复使用。当您打破对文件系统、数据库或Web服务的依赖时,模拟是必不可少的。如果您设置了真实的实例,您的测试将足够快和隔离。项目的基础设施不应影响域实体/域Mo的设计
var myClass1 = ClassBuilder.GetClass1();
var myClass2 = ClassBuilder.GetClass2();
var myClass1 = new Class1Builder.Build();
var myClass2 = new Class2Builder.WithSomeProprty().Build();