2011-09-30 58 views
1

我有一个简单的标准存储库,从数据库加载一个复合实体。它通过IDbConnection(我们可以模拟知识库访问IDbCommand,IDbTransaction,IDataReader)注入从数据库中读取完整实体树所需的所有依赖关系。单元测试,以验证存储库从数据库正确加载实体

public class SomeCompositionRootEntityRepository : 
    IRepository<SomeCompositionRoot> 
{ 
    public RecipeRepository(IDbConnection connection) { ... } 
    public void Add(SomeCompositionRootEntity item) { ... } 
    public bool Remove(SomeCompositionRootEntity item) { ... } 
    public void Update(SomeCompositionRootEntity item) { ... } 
    public SomeCompositionRootEntity GetById(object id) { ... } 
    public bool Contains(object id) { ... } 
} 

问题是,我将如何编写单元测试的这个好方法?如果我想测试一下reposity已经读取了整个对象树,并且它已经读取了它的正确性,我需要编写一个hughe mock来记录和验证树中每个对象的每个属性的读取。这真的是要走的路吗?

更新: 我想我需要重构我的存储库,以便将存储库功能和单元测试分解为更小的单元。这怎么能做到?

我确定我不想编写涉及从实际数据库读写数据的单元测试。

回答

1

的问题是:你要测试什么功能?

  1. 是否要测试您的存储库是否实际加载了某些内容?在这种情况下,我会写一些(!)通过数据库的测试。
  2. 还是要测试存储库方法内的功能?在这种情况下,你的模拟方法是适当的。
  3. 还是你想确保你的仓库的(平凡的)方法没有被破坏?在这种情况下,模拟和每种方法一次测试可能就足够了。

只问问自己测试应该确保什么,并沿着这个目标设计它们!

+0

对于任何给定的'SomeCompositionRootEntity'我想测试它读取所有对象和子对象,读取属性所需的所有列,正确组装对象树,写入所有对象,写入所有属性。由于这棵树相当复杂,我似乎必须写出几个非常庞大而庞大的单元测试。我想要正确的东西吗? – bitbonk

+0

所有这些功能都是在仓库的方法中编码的吗?如果是这样,你应该考虑分开测试方法来单独测试零件。简单的简短方法很好。如果此功能是从外部提供的(例如来自关系映射程序),则不应该对其进行详细测试。 – Arne

+0

我在.NET 2.0中,我不想使用任何第三方ORM。这种功能如何分解? – bitbonk

0

我想我明白你的问题,以便纠正我,如果我错了......

这是你越线从单元到整合。测试是有意义的(我自己写了这些),但是你并没有真正测试你的存储库,而是测试你的实体(SomeCompositionRoot)正确映射。它不是插入/更新,而是涉及对数据库的读取。

根据您使用的ORM,您可以通过一百万种不同的方式完成此操作,并且通常非常简单。

::编辑:: 这样的LINQ例如...

[TestMethod] 
    public void ShouldMapBlahBlahCorrectly() 
    { 
     CheckBasicMapping<BlahBlah>(); 
    } 

    private T CheckBasicMapping<T>() where T : class 
    { 
     var target = _testContext.GetTable<T>().FirstOrDefault(); 
     target.ShouldNotBeNull(); 
     return target; 
    } 
+0

我在.NET 2.0中,我不使用任何映射器。该存储库完成了所有使用“IDataReaders”和“IDbCommands”的工作。我应该重构存储库并引入某种映射器类,对象树中的每个实体类型都有一个类? – bitbonk

+0

尽管它很糟糕,但它可能是值得的。让T实现一些像“IMap”之类的接口,并允许它定义T的构造并让库调用该函数/方法 – jeriley