【问题标题】:Isolating Dependencies Without Inversion Of Control在不反转控制的情况下隔离依赖关系
【发布时间】:2010-11-10 19:43:53
【问题描述】:

我正在开发一个严重依赖消息队列、com+、数据库、httpcontext、静态实用程序类等的企业应用程序。

由于我们的系统中有 600 个项目,因此重写以使用控制反转似乎是不切实际的。 Typemock 声称它们是doesn't require you to rewrite your code to use IOC 唯一的隔离框架。

有人知道 TypeMock 是如何实现这一级别的功能的吗?是否有任何替代方案?即使我要重写我的应用程序以使用控制反转,我也必须为消息队列、httpcontext 等编写包装类。对我来说这听起来很荒谬,我认为 Typemock 是我唯一可行的选择是对还是错场景。

谢谢

【问题讨论】:

    标签: testing mocking typemock isolation


    【解决方案1】:

    Mocking non-virtual methods in C#

    如果不深入挖掘,答案就是 AOP 技术。由于您可以在事后拦截方法调用或更改方法调用,这使得添加模拟类/实例成为可能。

    这是对 AOP 的巧妙运用。

    如果你想自己做这件事(我敢肯定有一些陷阱......),请使用开源 Aspect weaver 框架:http://csharp-source.net/open-source/aspect-oriented-frameworks

    【讨论】:

    • 这种方法非常适合您拥有的代码 - 因此您可以将 AOP 放入其中。 Typemock 使用分析器 API,因此它还可以拦截您不拥有的代码(如共享点等)并使其可测试。
    【解决方案2】:

    大多数模拟框架确实依赖于某种形式的 IOC。这是因为 IOC 实际上是一种很好的做法。除了测试之外,假设您有一个查找数据库连接(而不是注入它)的类,现在数据库连接的类发生了变化。您不必重新编译代码 - 您应该能够更改注入的依赖项。从测试的角度来看,您可以做同样的事情,注入一个模拟数据库服务。

    为了更深入地了解您的问题。我将专注于逐步重构为注入而不是硬编码的查找框架。从大件开始,例如数据库和其他 3rd 方服务。当您重构它们时,您可以使用任何模拟框架(我使用过 EasyMock 并且我喜欢它,但还有其他的 - JMock、Mockito)。这些框架不需要包装类,但通常依赖于代理对象。当你创建一个模拟时,你实际上是在创建一个代理(它是你模拟的类类型的一个实例)。

    字节码操作(例如,Typemock 使用的面向方面)可能很危险,严重依赖它。很多时候,您可能还有其他工具也可以操作字节码(代码覆盖工具经常这样做),并且多个字节码操作可能会导致意外行为。

    最后,您可以看看 Groovy 之类的语言。 Groovy 可以很好地与 Java 配合使用(它可以编译为字节码),并且在语言中内置了 mock。一些使用 Groovy 搜索模拟对象的 Google 搜索应该会返回一些不错的结果。

    【讨论】:

    • 仅供参考,Typemock 与 NCover 等其他代码重写工具配合得很好,所以这根本不是问题。
    【解决方案3】:

    您认为 TypeMock(或其他类似的模拟工具)是唯一可行的选择是正确的。

    始终可以直接使用 AOP 工具来提供依赖关系的隔离,但这样做所需的工作量很大,因此在实践中不可行。

    对于 Java,JMockit 工具包可以隔离各种依赖项,而无需对生产代码进行任何必要的更改。

    在内部,JMockit 使用java.lang.instrument API 提供的功能。基本上,它允许在运行时重新定义方法/构造函数。重新定义意味着实现方法/构造函数的字节码被替换。对于相同的方法,可以多次执行此操作。此外,类可以在加载时转换(即,类中定义的任何方法或构造函数都可以在类可用于 JVM 之前更改其字节码)。

    【讨论】:

    • .Net 有没有免费的工具来替换方法等的字节​​码?
    • 据我所知,没有。我希望最终有人会创造它。
    【解决方案4】:

    如果你有这样的课程:

    public class MotherClass
    {
        private SubClass _subClass;
    
        public MotherClass()
        {
            _subClass = new SubClass();
        }
    }
    
    public class SubClass
    {
        public string SomeMethod()
        {
            return "Hello";
        }
    }
    

    没有 IoC。但是使用 Typemock Isolator,您仍然可以通过以下方式替换它:

        [TestMethod]
        public void TestMethod()
        {
            var fake = Isolate.Fake.Instance<SubClass>();
            Isolate.Swap.NextInstance<SubClass>().With(fake);
        }
    

    甚至像这样交换 SomeMethod 的结果:

            var fake = Isolate.Fake.Instance<SubClass>();
            Isolate.WhenCalled(() => fake.SomeMethod()).WillReturn("Bye");
    

    【讨论】:

      猜你喜欢
      • 2016-07-08
      • 2010-10-10
      • 1970-01-01
      • 2011-03-14
      • 1970-01-01
      • 1970-01-01
      • 2017-10-21
      • 1970-01-01
      相关资源
      最近更新 更多