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
}