【问题标题】:Mocking classes which dont have interface and even no virtual methods [duplicate]模拟没有接口甚至没有虚拟方法的类[重复]
【发布时间】:2017-08-06 15:15:02
【问题描述】:

我想模拟一个类的特定方法,我在模拟时面临的问题是该类没有任何接口,而且该方法不是虚拟的。

任何人都可以建议任何其他方式来实现模拟。

任何帮助将不胜感激。 提前致谢

【问题讨论】:

    标签: c#


    【解决方案1】:

    选项 1:TypeMock Isolator 或类似的东西,与正常的模拟相比,它允许更深入地混淆代码。

    选项 2:(如果可能,首选)改变设计,例如通过引入一个接口并创建一个委托实现,该实现只调用现有的对测试不友好的类。然后,您可以依赖该接口,在测试中对其进行模拟,并将其委托给“真实”实现以进行生产。

    这是假设你真的应该在嘲笑班级,当然。您不应该自动模拟代码使用的所有内容 - 我倾向于考虑模拟某些描述的“服务”,而我不会模拟(例如)List<T>

    【讨论】:

    • 选项 1 有什么问题?那它是一个非开源工具吗?或者它会据说导致糟糕的代码/设计?任何工具都可能被滥用,而且总是以某种方式,即使是人们经常用来嘲笑单纯的“getter”的更传统的模拟工具也是如此。在我(有偏见的)看来,“通过引入接口并创建委托实现来改变设计”更多可能导致错误的代码。
    • 抱歉,我应该在 发表评论后投反对票...
    • @Rogerio:我对它不是开源的没有太多问题——尽管显然它取决于上下文。在开源项目中用处不大。我个人会说,如果这真的是应该被嘲笑的东西,那么引入一个界面会导致更清晰的设计。
    • 是的,我是这么想的。但是我发现很多情况下我不想引入单独的接口,即使我想模拟类。一个示例:模拟在表示类或其他服务类中使用的业务服务类,其中每个服务类都包含特定于单个用例的业务逻辑代码。除了没有单独的接口之外,我更喜欢创建这样的类 sealed (C#) 或 final (Java),并使用用户提供的数据直接在更高级别的类中实例化它们。
    • WebClient 是一个基础设施级别的类,在特定应用程序的上下文中,更高级别的包装器可能非常有用;然而,这与特定于应用程序的业务服务类的情况非常不同。尽管如此,如果需要,它can 很容易被嘲笑。最后,我的主要观点是,我们不应该在默认情况下排除设计选项:如果开发人员认为有充分的理由模拟一个类,那么真正的模拟工具应该支持它。
    【解决方案2】:

    我建议重构你的代码;)所有通过从模拟类派生来创建模拟的模拟框架都要求方法是虚拟的(这是更多的 CLR 要求,而不是模拟框架)。

    要模拟非虚拟方法,您可以使用基于分析器的框架,例如 Moles 或 TypeMock Isolator,但这需要使用特殊的运行器运行测试运行器,该运行器会将 CLR 分析器附加到进程

    【讨论】:

      【解决方案3】:

      有诸如TypeMock Isolator 之类的单元测试框架允许您模拟非虚拟成员。

      【讨论】:

      • 另一种选择(虽然也是商业的)是JustMock
      【解决方案4】:

      要纯粹模拟遗留类,我会执行以下操作:

      1. 创建一个包含我打算使用的唯一公共成员的接口。 例如。

        public interface IDbContext {
            int SaveChanges();
        }
        
      2. 如果目标遗留类是密封的,那么我将创建一个代理/装饰器类,它实现新接口并调用底层方法/属性。

        public class MyDbContextProxy : IDbContext {
            DbContext _context = null;
            public MyDbContextProxy(DbContext interceptedContext) {
                _context = interceptedContext;
            }
            // decorated method
            public int SaveChanges() {
                _context.SaveChanges();
            }
        }
        
      3. 如果目标遗留类未密封,我将创建目标的后代并实现接口。 auto 类遵循接口。

        public class MyDbContextProxy : DbContext, IDbContext {
            // child adheres to interface by inheritence
        }
        

      现在您可以模拟 IDbContext。

      【讨论】:

        【解决方案5】:

        现在在 VS2012 中有类似 Fakes Framework 的东西。它是 Moles 的继承者(也能够像 TypeMock 一样模拟类等)。它仅在 Ultimate 版本中可用,所以我认为它不值得 Ultimate 的价格。

        但是,我想从其他角度讨论模拟类的问题。

        这是一种模拟类而不是接口的好方法,还是一种难闻的气味?我从来没有使用过 TypeMock(即使在小公司里也太贵了),但人们声称它有点“太强大”所以我想使用 Moq/RhinoMocks,但有时我想模拟/伪造一种方法,留下其他方法。这是我在测试期间思考模拟/伪造方法的糟糕方式吗?还是有时需要?

        【讨论】:

        • 假货框架的后期 +1 :)
        猜你喜欢
        • 1970-01-01
        • 2014-09-04
        • 2012-05-04
        • 2020-10-28
        • 2019-09-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多