【问题标题】:Are there any ways to mock entity framework calls that create new connections directly within methods有什么方法可以模拟直接在方法中创建新连接的实体框架调用
【发布时间】:2015-03-06 14:44:27
【问题描述】:

我是单元测试和模拟的新手。我正在做的项目有很多方法看起来像这样:

public bool MyMethod(int param, int param2)
{
    using (SomeEntity dBcontext = new SomeEntity())
    {
        FancyObj theobj = dBcontext.MyObjs.FirstOrDefault(l => l.ObjId == param2);
        if (theobj != null && theobj.CurrentSeason != param) //if season has changed then update
        {
            theobj .CurrentSeason = param;
            dBcontext.SaveChanges();

            return true;
        }
        return false;
    }
}

我正在使用 Telerik JustMock,除非我遗漏了什么,否则我无法模拟实体调用,因为它是在测试方法中直接实例化的。

修改方法/类以保存 SomeEntity 类型的属性是我唯一的解决方案吗?

【问题讨论】:

    标签: c# entity-framework unit-testing dependency-injection justmock


    【解决方案1】:

    新建一个所需依赖项的实例(而不是在构造函数中请求它)会破坏可测试性。本质上,通过使用new 运算符,您将应用程序实例化的关注点与应用程序逻辑的关注点混合在一起。

    依赖注入来救援!您的被测类应该要求在构造函数中完成其工作所需的所有内容,并依赖接口,而不是具体的实现。这样,您将能够提供虚假的实现来使您的单元测试完全隔离。

    【讨论】:

      【解决方案2】:

      如果不重构您的代码,我认为您可能无法使用传统的模拟框架,因为所有模拟框架都依赖于 virtualinterface 的方法。

      但是,如果您拥有 Visual Studio Premium 或 Ultimate 版,您可以使用 Microsoft Fakes,它允许您修改/替换/拦截对非虚拟方法和属性的调用(通过在第三个程序集中修改/注入 CIL 代码来工作)加载)。

      【讨论】:

        【解决方案3】:

        虽然从长远来看,依赖注入可能是更好的方法(它通常会改善代码的结构),但也有像 Typemock 这样的商业解决方案可以让您测试无法在常规方式。这有点喜忧参半,因为您可能会变得依赖于模拟框架,而不必获得可以通过使用更传统的模拟框架进行单元测试所鼓励的结构变化。但是,它应该允许您测试您所描述的情况。

        website 中的一个示例显示了他们如何能够获取在其计算函数中创建的对象的句柄。正如他们的一些其他示例所示,此句柄随后可用于设置对该依赖项的调用的期望:

        public static int Calculate(int a, int b)
        {
           var dependency = new Dependency();
           dependency.CheckSecurity("typemock", "rules");
           return a + b;
        }
        
        [TestMethod,Isolated]
        public void FakeConstructor()
        {
            // Fake the Dependency constructor
            var fakeHandle = Isolate.Fake.NextInstance<dependency>();
            var result = ClassUnderTest.Calculate(1, 2);
            Assert.AreEqual(3, result);
        }
        

        有各种不同的定价选项,我不确定每个层级的价格是多少,但是如果您真的不想更改代码并且财力雄厚,则可能值得考虑。

        【讨论】:

          【解决方案4】:

          是的,可以使用 JustMock 的商业版本来安排 new 表达式的返回值。

          var mock = Mock.Create<SomeEntity>();
          Mock.Arrange(() => new SomeEntity()).Returns(mock);
          

          从这里开始,您可以安排模拟以获得测试所需的行为。如果您使用的是 EF6,那么您可以尝试插入 JustMock 的 Telerik.JustMock.EntityFramework 为您的测试创建内存模拟数据库上下文。

          【讨论】:

            猜你喜欢
            • 2011-06-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-02-15
            • 2016-07-18
            • 1970-01-01
            相关资源
            最近更新 更多