2

我是单元测试和模拟的新手。我正在处理的项目有很多方法,如下所示:

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 类型的属性是我唯一的解决方案吗?

4

4 回答 4

2

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

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

于 2015-03-06T14:59:45.333 回答
1

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

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

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);
}

有各种不同的定价选项,我不确定你能从每一层得到什么,但如果你真的不想更改代码并且财力雄厚,那么可能值得考虑。

于 2015-03-09T12:33:19.947 回答
1

如果不重构您的代码,我认为您可能对传统的模拟框架不走运,因为所有模拟框架都依赖于方法要么virtualinterface.

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

于 2015-03-06T15:02:40.173 回答
0

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

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

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

于 2015-03-10T12:14:22.923 回答