Why does the property I want to mock need to be virtual?

asp.net-mvc, c#, controller, moq, unit-testing

Solution

Moq and other similar mocking frameworks can only mock interfaces, abstract methods/properties (on abstract classes) or virtual methods/properties on concrete classes.

This is because it generates a proxy that will implement the interface or create a derived class that overrides those overrideable methods in order to intercept calls.

Problem

I'm doing some unit testing, and mocking some properties using Moq. Now, this is a Controller test (ASP.NET MVC 3). My Controllers derive from an abstract controller, called AbstractController. This controller has a dependency on the Http Context (in order to do things like theming, domain-specific logic based on HTTP HOST headers, etc). This is done via a property called WebSiteSettings: ``` public abstract class AbstractController : Controller { public WebSiteSettings WebSiteSettings { get; private set; } // other code } ``` Notice the private set - the ctor sets it up. So, i changed it to used an interface, and that's what i've mocked: ``` public IWebSiteSettings WebSiteSettings { get; private set; } ``` I then created a "FakeWebSiteSettings", which mocks the Http Context in order for it to read the HTTP headers. The problem is, when i run the test, i get a NotSupportedException: Invalid setup on a non-virtual (overridable in VB) member: x => x.WebSiteSettings Here's the relevant mocking code: ``` 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); ``` If i make the `WebsiteSettings` property virtual - the test passes. But i can't understand why i need to do this. I'm not actually overriding the property, i'm simply mocking how it is setup. Am i missing something, or doing this wrong?

Original source