2

我正在使用 Entity Framework 4.1 进行数据库访问,并希望对以下代码进行单元测试:

// Get all the entities including children
using (MyContext context = new MyContext())
{
    return context.EmployeeProfiles.Include("EmployeeProperties").ToList();
}

我正在使用 Moles 来消除数据库依赖关系,但是我被卡住了。我应该开始研究实体框架中的哪一点。

我正在关注这个示例,但它适用于 LINQ-To-SQL。

我还在考虑调试/跟踪实体框架,以确定在调用数据库之前要拦截哪个函数。但是,似乎没有可供 Entity Framework 4.1 跟踪的源代码。见讨论

谁能指导我应该在 DbContext 中删除哪些功能,以便我可以获取 EmployeeProfiles 列表?

4

2 回答 2

0

在我看来,不是通过存储库模式消除对 EF 的依赖,而是在尝试模拟 EF 的特定行为。我看不出尝试这样做有什么意义,这将非常困难,EF 并不是要被嘲笑的。

您的存储库大概是这样的:

public interface IRepository
{
      IEnumerable<EmployeeProfiles> EmployeeProfiles { get; }
}

public class Repository
{
    public IEnumerable<EmployeeProfiles> EmployeeProfiles
    {
        get
        {
            // Get all the entities including children     
            using (MyContext context = new MyContext())     
            {
                return context.EmployeeProfiles.Include("EmployeeProperties").ToList();     
            }
        }
    }
}

这样,您就删除了关于如何返回 EmployeeProfiles 的存储库依赖项。现在您可以随心所欲地模拟(尚未使用 Moles),但使用 Moq,您可以执行以下操作:

public void TestEmptyList()
{
    var mock = new Mock<IRepository>();
    var expected = new List<EmployeeProfiles>();
    mock.SetupGet(ep => ep.EmployeeProfiles).Returns(expected);

    var actual = mock.Object.EmployeeProfiles;

    Assert.AreEqual(expected, actual);
}

因此,如果您将要从数据库中抽象出来的方法/属性放入存储库接口中,那么您可以模拟出您想要测试它可能返回的任何值。

也许你正在这样做,我不确定。我不明白您为什么要对 EF 进行单元测试,您希望获得什么?这将非常困难,它不是为模拟而设计的(很少有接口/虚拟)。您返回的任何数据模拟,这实际上是您真正感兴趣的所有内容,都将按照上述方式完成。

于 2011-11-17T15:43:15.620 回答
0

这是完全可能的,并且在我看来是有效的。是的,您可以使用存储库模式并模拟您的存储库,这通常已经足够了。

但是,我看到了两个嘲笑 EF 的论点:

  1. EF 已经是实际数据库的抽象/存储库,不需要围绕它编写另一个存储库。
  2. 您通过 EF 编写的任何存储库都是您的代码。因此,您应该对其进行测试,因为迟早您最终会添加需要覆盖的逻辑。

在这一点上,这有点像一场圣战,但有一些论据支持你正在做的事情。

因此,要对 Moles 进行此操作,您需要做两件事。首先,更改创建 DbContext 的模板,以便所有表的返回类型都不IDbSet<>DbSet<>.

然后,在您的测试项目中,为 IDbSet 添加一个测试类实现。我发现这个很好用。

现在,在您的测试中,您可以执行以下操作:

List<EmployeeProfile> testProfiles = /*your test data here*/;
MMyContext.AllInstances.EmployeeProfilesGet  = (instance) => 
{
    return new InMemoryDbSet<EmployeeProfile>(testProfiles);
};


// Get all the entities including children
using (MyContext context = new MyContext())
{
    return context.EmployeeProfiles.Include("EmployeeProperties").ToList();
}

它快速、简单,并且允许您测试您的代码,直到它离开您的控制。

于 2013-11-08T21:24:29.180 回答