【发布时间】:2017-08-06 15:15:02
【问题描述】:
我想模拟一个类的特定方法,我在模拟时面临的问题是该类没有任何接口,而且该方法不是虚拟的。
任何人都可以建议任何其他方式来实现模拟。
任何帮助将不胜感激。 提前致谢
【问题讨论】:
标签: c#
我想模拟一个类的特定方法,我在模拟时面临的问题是该类没有任何接口,而且该方法不是虚拟的。
任何人都可以建议任何其他方式来实现模拟。
任何帮助将不胜感激。 提前致谢
【问题讨论】:
标签: c#
选项 1:TypeMock Isolator 或类似的东西,与正常的模拟相比,它允许更深入地混淆代码。
选项 2:(如果可能,首选)改变设计,例如通过引入一个接口并创建一个委托实现,该实现只调用现有的对测试不友好的类。然后,您可以依赖该接口,在测试中对其进行模拟,并将其委托给“真实”实现以进行生产。
这是假设你真的应该在嘲笑班级,当然。您不应该自动模拟代码使用的所有内容 - 我倾向于考虑模拟某些描述的“服务”,而我不会模拟(例如)List<T>。
【讨论】:
sealed (C#) 或 final (Java),并使用用户提供的数据直接在更高级别的类中实例化它们。
WebClient 是一个基础设施级别的类,在特定应用程序的上下文中,更高级别的包装器可能非常有用;然而,这与特定于应用程序的业务服务类的情况非常不同。尽管如此,如果需要,它can 很容易被嘲笑。最后,我的主要观点是,我们不应该在默认情况下排除设计选项:如果开发人员认为有充分的理由模拟一个类,那么真正的模拟工具应该支持它。
我建议重构你的代码;)所有通过从模拟类派生来创建模拟的模拟框架都要求方法是虚拟的(这是更多的 CLR 要求,而不是模拟框架)。
要模拟非虚拟方法,您可以使用基于分析器的框架,例如 Moles 或 TypeMock Isolator,但这需要使用特殊的运行器运行测试运行器,该运行器会将 CLR 分析器附加到进程
【讨论】:
有诸如TypeMock Isolator 之类的单元测试框架允许您模拟非虚拟成员。
【讨论】:
要纯粹模拟遗留类,我会执行以下操作:
创建一个包含我打算使用的唯一公共成员的接口。 例如。
public interface IDbContext {
int SaveChanges();
}
如果目标遗留类是密封的,那么我将创建一个代理/装饰器类,它实现新接口并调用底层方法/属性。
public class MyDbContextProxy : IDbContext {
DbContext _context = null;
public MyDbContextProxy(DbContext interceptedContext) {
_context = interceptedContext;
}
// decorated method
public int SaveChanges() {
_context.SaveChanges();
}
}
如果目标遗留类未密封,我将创建目标的后代并实现接口。 auto 类遵循接口。
public class MyDbContextProxy : DbContext, IDbContext {
// child adheres to interface by inheritence
}
现在您可以模拟 IDbContext。
【讨论】:
现在在 VS2012 中有类似 Fakes Framework 的东西。它是 Moles 的继承者(也能够像 TypeMock 一样模拟类等)。它仅在 Ultimate 版本中可用,所以我认为它不值得 Ultimate 的价格。
但是,我想从其他角度讨论模拟类的问题。
这是一种模拟类而不是接口的好方法,还是一种难闻的气味?我从来没有使用过 TypeMock(即使在小公司里也太贵了),但人们声称它有点“太强大”所以我想使用 Moq/RhinoMocks,但有时我想模拟/伪造一种方法,留下其他方法。这是我在测试期间思考模拟/伪造方法的糟糕方式吗?还是有时需要?
【讨论】: