c# - 为什么我要模拟的属性需要是虚拟的?

标签 c# asp.net-mvc unit-testing controller moq

我正在做一些单元测试,并使用 Moq 模拟一些属性。

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

此 Controller 依赖于 Http 上下文(以便执行诸如主题化、基于 HTTP HOST header 的域特定逻辑等操作)。

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

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

   // other code
}

注意私有(private)集——ctor 设置它。所以,我将其更改为使用一个界面,这就是我所 mock 的:

public IWebSiteSettings WebSiteSettings { get; private set; }

然后我创建了一个“FakeWebSiteSettings”,它模拟 Http 上下文以便它读取 HTTP header 。

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

Invalid setup on a non-virtual (overridable in VB) member: 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);

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

但我不明白为什么我需要这样做。我实际上并没有覆盖该属性,我只是在 mock 它的设置方式。

我是不是遗漏了什么,或者做错了什么?

最佳答案

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

这是因为它会生成一个代理,该代理将实现接口(interface)或创建一个派生类来覆盖那些可覆盖的方法以拦截调用。

关于c# - 为什么我要模拟的属性需要是虚拟的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5670902/

相关文章:

c# - 从未定义样式的 ASP.NET GridView 行

asp.net - 从枚举 .NET Core 中选择列表

c# - 人员选取器控件在 asp.net mvc 应用程序中的实现

c# - 如何测试谷歌搜索按钮

java - 创建目录的单元测试代码

c# - 用于 ASP.NET 的自定义 Javascript Ajax

c# - 什么时候去静态类?

c# - Visual Studio/IIS Express 间歇性错误

asp.net-mvc - MVC 对 Office 365 AD 进行身份验证

java - 如何对我的 MainActivity 进行单元测试?