我可以创建一个符合接口的模拟并且还知道其基础 class 上的方法吗?

Can I create a mock that conforms to an interface and is also aware of methods on its base class?

我正在使用 Moq 在 WinForms 应用程序中测试演示者。主持人有观点。视图符合ISomeControl,继承自UserControl

在测试这个演示者时,我想测试视图上的 Show() 方法被调用了。

所以我创建了一个这样的模拟:

var someControl = new Mock<ISomeControl>();

但这就是问题所在:在我的应用程序中,有一个地方我将 ISomeControl 转换为 Control,这样我就可以调用基础 class Show()。因为 Mock 只知道它是一个 ISomeControl,我收到以下错误:

Unable to cast object of type 'Castle.Proxies.ObjectProxy_1' to type 'System.Windows.Forms.Control'.

有办法解决这个问题吗?

创建一个基础 abstract class 继承 ISomeControlUserControl 以便在单元测试中进行模拟。

public abstract class SomeDummyControl : UserControl, ISomeControl { 
    //...
}

这应该允许模拟识别这两种类型。

var mock = new Mock<SomeDummyControl>();
//...arrange setup

var dummyControl = mock.Object;
//...pass the dummy as a dependency

//just to show that it should be able to cast
var control = dummyControl as Control;
var someControl = dummyControl as ISomeControl;

mock可以在需要的时候这样验证

mock.Verify(m => m.Show(), Times.AtLeastOnce()); //verifies that the Show method was called.

在此处阅读有关最小起订量的更多信息Moq Quickstart

一个mock可以实现多个接口

Moq Quick Start 中的一个片段展示了如何做到这一点:

// implementing multiple interfaces in mock
var foo = new Mock<IFoo>();
var disposableFoo = foo.As<IDisposable>();
// now the IFoo mock also implements IDisposable :)
disposableFoo.Setup(df => df.Dispose());

//implementing multiple interfaces in single mock
var foo = new Mock<IFoo>();
foo.Setup(f => f.Bar()).Returns("Hello World");
foo.As<IDisposable>().Setup(df => df.Dispose());