views:

256

answers:

2

Hi folks,

i have the following code, which fails during runtime...

var mock = new Mock<ControllerContext>();
mock.SetupGet(x => x.HttpContext.Request
    .ServerVariables["HTTP_HOST"]).Returns(domain);

** RunTime Error: Invalid setup on non-overridable property

I've got some code in my controller, which needs to check the domain the user has requested/gone to.

I'm not sure how to mock it up? any ideas?

PS. I'm using the Moq framewoke in the above example .. so I'm not sure if that's an issue, etc.?

+2  A: 

You can't mock the indexer on a NameValueCollection because it's not virtual. What I would do is mock the ServerVariables property since that IS virtual. You can fill in your own NameValueCollection. See below

Here's what I would do:

 var context = new Mock<ControllerContext>();
 NameValueCollection variables = new NameValueCollection();
 variables.Add("HTTP_HOST", "www.google.com"); 
 context.Setup(c => c.HttpContext.Request.ServerVariables).Returns(variables);
 //This next line is just an example of executing the method 
 var domain = context.Object.HttpContext.Request.ServerVariables["HTTP_HOST"];
 Assert.AreEqual("www.google.com", domain);
Eric
HA! Of course!! <3 .. Also, You used `context.Setup`. I was using `context.SetupGet` ... any reason why you used that? (i'm really really new to Moq...)
Pure.Krome
There is probably some kind of difference, but I'm also not an expert on the intricacies so I just use Setup() across the board for consistency :) This post seems to explain the differences a little, although I would gladly hear from an expert on this as well: http://stackoverflow.com/questions/1073846/need-help-understand-moq-better
Eric
+1  A: 

You can cover HttpContext with interface and mock it in your tests:

interface IHttpContextValues
{
    string HttpHost { get; }
}

class HttpContextValues : IHttpContextValues
{
    public string HttpHost
    {
        get { return HttpContext.Current.Request.ServerVariables["HTTP_HOST"]; }
    }
}

class BaseController : Controller
{
    public IHttpContextValues HttpContextValues;
    BaseController()
    {
        HttpContextValues = new HttpContextValues();
    }
}

Then you use HttpContextValues instead of ControllerContext.HttpContext in your controller code. You don't have to make any combinations about mocking.

LukLed