在DDD / TDD应用程序中测试持久层

时间:2009-03-31 22:39:09

标签: c# nhibernate tdd domain-driven-design

如果我有以下域对象:

public class Customer
{
    public virtual Guid Id { get; set; }
    public virtual string Name { get; set; }
    public virtual ISet<Order> Orders { get; set; }

    public Customer()
    {
        Orders = new HashedSet<Order>();
    }

    public virtual void AddOrder(Order order)
    {
        order.Customer = this;
        Orders.Add(order);
    }
}

使用以下NHibernate映射:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="Examples" assembly="Examples">
  <class name="Customer">
      <id name="Id">
        <generator class="guid.comb" />
      </id>
      <property name="Name" length="50"/>
      <set name="Orders" table="CustomerOrder" cascade="all-delete-orphan" lazy="true">
        <key column="CustomerId"/>
        <many-to-many class="Order" column="OrderId"/>
      </set>
  </class>
</hibernate-mapping>

此测试中有任何价值吗?

[Test]
public Save_NameWritten_SameNameIsReadback()
{
    var expected = new Customer { Name = "Fred Quimby" };
    _repo.Save(c);
    var actual = _repo.Find(expected.Id);
    Assert.AreEqual(expected.Name, actual.Name);
}

人们通常会像这样测试他们的持久层吗?确保每个字段都是单独保留的?老实说,我不确定最佳做法是什么。我可以看到测试具有长字符串和父/子关系的东西 - 但整数和日期呢?这有点过头了吗?

我这里只讨论持久层,而不是域层中的业务逻辑。为此,我会模拟存储库,而在这里我正在验证存储库实际上保存了我告诉它保存的东西。如果有人忘记映射字段,或者它们在映射中有伪造的字符串长度怎么办?

是否有任何工具可以在.NET中自动生成这些类型的测试?或者那是“坏”?

2 个答案:

答案 0 :(得分:3)

如果您确保在不同的会话中保存和获取数据,那么您可以有效地确保映射是正确的 - 这是值。

最好的方法是在内存数据库中使用类似PersistenceSpecification(这里是关于它的post)来自流畅的NHibernate,它可以在不同的会话中为你插入和选择数据。

答案 1 :(得分:0)

这些测试具有很大的价值,因为它们最终是验证您是否真的可以与数据库通信的唯一方法。一旦验证了您有一个工作存储库,就可以在其他单元测试中模拟对存储库的调用,如您所述。

请谨慎使用内存数据库 - 因为您需要知道目标数据库是否正常工作。还要注意这些测试中的会话使用情况。如果您确实想在加载时点击数据库,请确保在不同的会话中进行保存和查找。

使用这些有线数据库测试可以验证的内容很少:

  • 字符串的边界长度
  • 延迟加载。您可以使用分离的会话来验证您不希望急切加载的连接对象的延迟加载异常,反之亦然。当有人无意中通过对象图添加导航路径导致整个数据库被加载时,这对于更复杂的域层次结构非常重要。
  • 外键和唯一约束。
  • 使用大型数据集调用存储库的效率。