Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/302.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 模拟没有接口甚至没有虚拟方法的类_C# - Fatal编程技术网

C# 模拟没有接口甚至没有虚拟方法的类

C# 模拟没有接口甚至没有虚拟方法的类,c#,C#,我想模拟一个类的特定方法,模拟时我面临的问题是该类没有任何接口,而且该方法不是虚拟的 有谁能提出其他实现模拟的方法吗 任何帮助都将不胜感激。 提前感谢有一些单元测试框架,例如,允许您模拟非虚拟成员。选项1:或类似的东西,它允许对代码进行比普通模拟更深的混乱 选项2:(如果可能,首选)更改设计,例如通过引入接口并创建一个只调用现有测试不友好类的委托实现。然后,您可以依赖该接口,在测试中对其进行模拟,并将其委托给“真正的”生产实现 当然,这是假设你真的应该嘲笑这个班。你不应该自动模仿你的代码使用的所

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

有谁能提出其他实现模拟的方法吗

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

有一些单元测试框架,例如,允许您模拟非虚拟成员。

选项1:或类似的东西,它允许对代码进行比普通模拟更深的混乱

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


当然,这是假设你真的应该嘲笑这个班。你不应该自动模仿你的代码使用的所有东西——我倾向于模仿某种描述的“服务”,而我不会模仿(例如)
List

我建议重构你的代码;)所有通过从mocked类派生来创建mock的mocking框架都要求方法是虚拟的(这比mocking框架更需要CLR)


要模拟非虚拟方法,您可以使用基于探查器的框架,如Moles或TypeMock Isolator,但是这需要使用特殊的runner运行test runner,该runner将CLR profiler附加到进程中,以完全模拟遗留类。我将执行以下操作:

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

  • 如果目标遗留类是密封的,那么我将创建一个代理/装饰器类,该类实现新接口,并只调用底层方法/属性

    public class MyDbContextProxy : IDbContext {
        DbContext _context = null;
        public MyDbContextProxy(DbContext interceptedContext) {
            _context = interceptedContext;
        }
        // decorated method
        public int SaveChanges() {
            _context.SaveChanges();
        }
    }
    
  • 如果目标遗留类未密封,我将创建目标的子代并实现接口。该类自动附着到接口

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

  • 现在您可以模拟IDbContext。

    现在VS2012中有类似于Fakes框架的东西。它是Moles的继承者(也可以模拟类等,比如TypeMock)。它只提供终极版,所以我不认为它值终极版的价格

    但是,我想从另一个角度讨论模拟类的问题


    这是模拟类而不是接口的好方法,还是一种坏味道?我从来没有使用过TypeMock(它太贵了,甚至不能在小公司里考虑),但是人们声称它有点“太强大了”,所以我想使用MOQ/RomoMoCK,但有时我想模仿/仿效一种方法而离开其他方法。这是我在测试中思考模仿/伪造方法的糟糕方式?或者它有时是必需的?

    一个替代方案(尽管也是商业的)是。选项1有什么问题?它是一个非开源工具吗?或者它可能会导致糟糕的代码/设计?任何工具都可能被误用,而且总是以这样或那样的方式,甚至是人们经常嘲笑的更传统的模仿工具,仅仅是“获得者”。在我(有偏见的)看来,“通过引入接口和创建委托实现来改变设计”更有可能导致糟糕的代码。对不起,我应该在评论后投反对票…@Rogerio:我对它不是开源没有太大问题,尽管它显然取决于上下文。它在开源项目中没有多大用处。就我个人而言,如果这真的是一件值得嘲笑的事情,那么引入一个界面将导致一个更清晰的设计。是的,我是这么想的。但是我发现很多情况下我不想引入单独的接口,即使我想模拟这个类。一个示例:模拟表示类或其他服务类中使用的业务服务类,其中每个服务类包含特定于单个用例的业务逻辑代码。与没有单独的接口相比,我更喜欢将此类类
    密封
    (C#)或
    最终
    (Java),并使用用户提供的数据直接在更高级别的类中实例化它们。
    WebClient
    是一个基础结构级别的类,在特定应用程序的上下文中,更高级别的包装器可能非常有用;但是,这与特定于应用程序的业务服务类的情况非常不同。不过,如果需要的话,它很容易被嘲笑。最后,我的主要观点是,默认情况下,我们不应该排除设计选项:如果开发人员认为有很好的理由模拟一个类,那么真正的模拟工具应该支持它
    public class MyDbContextProxy : DbContext, IDbContext {
        // child adheres to interface by inheritence
    }