【发布时间】:2011-11-09 02:02:18
【问题描述】:
假设我有一项服务:
UserService
它有 2 个公共方法:
Method1, Method2
我正在测试 Method1,但 Method1 调用 Method2。
如何模拟(或者更正确的词是存根)对 Method2 的调用。
如果我模拟 UserService,那我现在就不能真正测试 Method1 了吗?
【问题讨论】:
假设我有一项服务:
UserService
它有 2 个公共方法:
Method1, Method2
我正在测试 Method1,但 Method1 调用 Method2。
如何模拟(或者更正确的词是存根)对 Method2 的调用。
如果我模拟 UserService,那我现在就不能真正测试 Method1 了吗?
【问题讨论】:
除非你削弱这些方法之间的耦合,否则这是无法做到的,可能是通过引入抽象/接口。您当前的 UserService 实现意味着 Method1 和 Method2 之间的强耦合。
【讨论】:
如果我正确理解您的问题,您可以使用CallBase:
如果没有期望覆盖成员,则调用基类实现(在 Rhino Mocks 中也称为“Partial Mocks”)
使用CallBase = true 创建您的模拟,设置Method2 以返回您想要测试的任何值,然后调用Method1。
举个例子:
class Program
{
static void Main(string[] args)
{
var mock = new Mock<UserService> { CallBase = true };
mock.Setup(m => m.Method2()).Returns("Mock 2");
Console.WriteLine(mock.Object.Method1());
Console.ReadLine();
}
}
public class UserService
{
public virtual string Method1()
{
return "Method 1 :: " + Method2();
}
public virtual string Method2()
{
return "Method 2";
}
}
【讨论】:
我仍在为这个问题苦苦挣扎,“应该我应该模拟对 Method2 的调用吗?”我倾向于说,“不”。如果类在内部使用这两种方法作为其逻辑的一部分,那么它们都是测试的一部分。模拟用于依赖于 UserService,而不是内部实现细节。
简而言之,虽然我不知道有任何模拟工具可以做到这一点,但我认为一开始就不应该这样做。
【讨论】:
Moq 不能。您可以考虑使用 Moles,它确实提供了这种粒度。如果你 Mole 自己的程序集,你可以在方法/属性级别而不是在类/接口级别进行模拟。
【讨论】: