为什么我想要模拟的属性需要是虚拟的?

RPM*_*984 39 c# asp.net-mvc unit-testing controller moq

我正在进行一些单元测试,并使用Moq模拟一些属性.

现在,这是一个Controller测试(ASP.NET MVC 3).我的控制器派生自一个名为AbstractController抽象控制器.

该控制器依赖于Http Context(为了做主题,基于HTTP HOST头的特定于域的逻辑等).

这是通过名为WebSiteSettings的属性完成的:

public abstract class AbstractController : Controller
{
   public WebSiteSettings WebSiteSettings { get; private set; }

   // other code
}
Run Code Online (Sandbox Code Playgroud)

注意私人集 - ctor设置它.所以,我把它改成使用了一个界面,这就是我所嘲笑的:

public IWebSiteSettings WebSiteSettings { get; private set; }
Run Code Online (Sandbox Code Playgroud)

然后我创建了一个"FakeWebSiteSettings",它嘲笑Http Context以便它读取HTTP头.

问题是,当我运行测试时,我得到一个NotSupportedException:

非虚拟(在VB中可覆盖)成员的设置无效:x => x.WebSiteSettings

这是相关的模拟代码:

var mockWebSiteSettings = new Mock<FakeWebSiteSettings>();
var mockController = new Mock<MyController>(SomeRepository);
mockController.Setup(x => x.WebSiteSettings).Returns(mockWebSiteSettings.Object);

_controller = mockController.Object;

var httpContextBase = MvcMockHelpers.FakeHttpContext();
httpContextBase.Setup(x => x.Request.ServerVariables).Returns(new NameValueCollection
    {
        {"HTTP_HOST","localhost.www.mydomain.com"}, 
});
_controller.SetFakeControllerContext(httpContextBase.Object);
Run Code Online (Sandbox Code Playgroud)

如果我将WebsiteSettings属性设为虚拟 - 测试通过.

但我无法理解为什么我需要这样做.我实际上并没有覆盖这个属性,我只是嘲笑它是如何设置的.

我错过了什么,或做错了吗?

aqw*_*ert 59

Moq和其他类似的模拟框架只能模拟接口,抽象方法/属性(在抽象类上)或具体类上的虚方法/属性.

这是因为它生成了一个代理,它将实现接口或创建一个派生类,该类覆盖那些可重写的方法以拦截调用.

  • 只有Moq的方式.其他如TypeMock Isolator,Moles可以拦截这些方法/属性 (2认同)