【发布时间】:2018-09-15 20:19:11
【问题描述】:
假设我有以下设置:
public interface IFoo
{
string DoSomething();
string DoAnotherThing();
}
public sealed class Bar : IFoo
{
public string DoAnotherThing() => "DoAnotherThing";
public string DoSomething() => "DoSomething";
}
使用 Moq,我想模拟出Bar 的方法之一,但调用另一个方法的实现。我知道我可以通过创建一个委托给Bar 的包装类来做到这一点,如下所示:
public class MockableBar : IFoo
{
private readonly IFoo _bar;
public MockableBar(IFoo bar) => _bar = bar;
public virtual string DoAnotherThing() => _bar.DoAnotherThing();
public virtual string DoSomething() => _bar.DoSomething();
}
然后像这样嘲笑它:
var fake = new Moq.Mock<MockableBar>(new Bar()) { CallBase = true };
fake.Setup(_ => _.DoSomething()).Returns("Mock");
Assert.AreEqual("DoAnotherThing", fake.Object.DoAnotherThing());
Assert.AreEqual("Mock", fake.Object.DoSomething());
有没有更通用的方法来完成这个,所以我不必为我想在这个机制中测试的每个接口创建一个新的包装类?
【问题讨论】:
-
为什么需要包装类?你能不能只对
Bar进行部分模拟并获得相同的结果? -
为什么酒吧是密封的?这似乎是问题所在。
-
Bar 已密封,因为该类并非设计为继承自。
-
A contrary opinion. Unsealing Bar 会让您的生活变得更简单。
-
如果在运行时自动生成代理类(类似于你的
MockableBar)怎么办?虽然我同意 Michael 的观点,但毫无理由地密封课程通常会带来很多痛苦(不是给你,而是给你图书馆的用户)。我打了很多次,我需要继承以实现我的目标的第三方库中的那个类是密封的,虽然我从来没有想过“我希望那个类是密封的,如果不这样做对我来说是非常有益的能够继承它”。不过,这当然是基于意见的。