我应该如何分离EF代码首次DAL的集成测试和DAL客户端的纯单元测试?

时间:2012-08-30 06:41:21

标签: entity-framework unit-testing ef-code-first integration-testing entity-framework-5

看到一些针对模拟测试EF的强烈建议,特别是Code First,我决定对专用于测试的SqlCe数据库进行集成测试,然后在工作单元和存储库的下游使用纯单元测试通过DbContext和DbSet。

我只是不清楚在哪里画线以及测试在哪里。我知道当我确信DAL特定的集成测试涵盖其内部时,我可以在我的服务层中模拟DAL,但是我在DAL中测试什么?似乎没有太多的点测试,看看我是否可以保存和读取对象,因为EF是外部的并且已经过测试。

4 个答案:

答案 0 :(得分:1)

您将使用集成测试在DAL中测试映射和查询。例如:

public class Service {
   private readonly IDAL _dal;

   public Service(IDAL dal) {
       // Not null validation here
       _dal = dal;
   }

   public void DoSomething() {
       SomeData data = FindSomeData();
       // Do some logic
       _dal.Commit();
   }

   protected virtual SomeData FindSomeData() {
       return _dal.SomeData.Where(...).FirstOrDefault();
   }
}

这是一个非常简化的例子,显示:

  • Service依赖于DALDAL接口通过构造函数注入传递。
  • Service包含您要测试的公共DoSomething方法,以了解逻辑是否正确执行。但是这种方法也依赖于数据库查询和数据库持久性(Commit)。
  • 查询是您逻辑的一部分,但执行此类查询是另外一个问题,因此它由自己的方法处理。在更复杂的情况下,此方法可以在其他类中注入Service类(存储库)。这些查询方法的关键标准是:
    • 他们不会返回IQueryable
    • 他们不接受Expression<>作为参数

如何对DoSomething方法进行单元测试:

  • 在这个简单的示例中,您的测试类将派生自Service类并覆盖FindSomeData以返回测试数据。在注射的情况下,您将为注入的类定义假。
  • 您还将模拟IDAL,然后您可以验证Commit被称为

您应该使用哪种集成测试:

  • 您应该为查询真实数据库的FindSomeData创建测试
  • 一般情况下,您还应该对Commit进行集成测试,但实现起来比较困难,因为该示例直接从DoSomething调用了提交。您不希望再次测试该方法,同时Commit方法具有太多通用情况,因为它只是将所有更改从当前上下文刷新到数据库。我通常有单独的测试来插入,更新和删除每个实体类型。当DoSomething方法执行一些复杂的修改时,您可以将方法拆分为两个方法,一个由单元测试处理,一个是实际逻辑,另一个是由不同持久性场景的集成测试覆盖,可以由您的逻辑生成。

答案 1 :(得分:0)

实体框架已经过测试,但您的DAL,尤其是映射,并非如此。我更喜欢使用集成测试向我展示我的映射是正确的,而且更好的是,我可以成功地对我的数据库执行所有CRUD操作。

答案 2 :(得分:0)

我们通常在数据库方面测试的是,是否可以正确插入,更新,删除复杂的对象图;基本上测试更复杂的映射 在我看来,测试是否可以插入具有3个原始值属性的对象并没有多大意义,因为那时你永远不会看到它的结束。
我们喜欢乐观(简单的东西会起作用),我们测试更复杂的关联,如果我们在映射中遇到错误(例如应该删除但不是的对象),我们会编写一个额外的测试为此。
从商业角度来衡量绝对一切通常是不明智的;你应该首先关注高风险/高伤害的东西,然后沿着严重程度上下去,直到你觉得它不再值得。

答案 3 :(得分:0)

1)进行一组测试映射的集成测试

2)让你的DAL 非常重量轻但具有足够的力量来构建查询,例如:

public interface IDb
{
    IQueryable<T>Query<T>();
    ... (save, delete, get-by-id methods)...
}

3)编写对象,这些对象封装了构建针对DAL

的查询的逻辑
public class MuppetSearch
{
    public MuppetColor? Color { get; set;}
    public string Name{ get; set; }
    public IQueryable<Muppet> ConstructQuery(IDb db)
    {
        var query = db.Query<Muppet>();
        if(Color.HasValue)
        {
            query = query.Where(m=>m.Value == Color.Value);
        }
        if(!String.IsNullOrEmpty(Name))
        {
            query = query.Where(m=>m.Name.Contains(Name));
        }
        return query;
    }
}

4)测试那些,模拟你需要的所有数据应该是非常简单的

5)在您的服务中使用搜索类来进行查询构建