One of my services uses server variable provided by IIS through such code
var value = System.Web.HttpContext.Current.Request.ServerVariables["MY_CUSTOM_VAR"];
What I've tried is to mock those object and insert my own variable/collection and check few cases(e.g. variable is missing, value is null ...) I'm able to create instances of HttpContext, HttpRequest, HttpResponse and assign them properly however each of them is just a plain class without interface or virtual properties and initialization of ServerVariables happens somewhere under the hood.
HttpContext mocking:
var httpRequest = new HttpRequest("", "http://excaple.com/", "");
var stringWriter = new StringWriter();
var httpResponse = new HttpResponse(stringWriter);
var httpContextMock = new HttpContext(httpRequest, httpResponse);
HttpContext.Current = httpContextMock;
Attempt #1 Call private method via reflection
var serverVariables = HttpContext.Current.Request.ServerVariables;
var serverVariablesType = serverVariables.GetType();
MethodInfo addStaticMethod = serverVariablesType.GetMethod("AddStatic", BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.NonPublic);
addStaticMethod.Invoke(serverVariables, new object[] {"MY_CUSTOM_VAR", "value"});
Failed with error saying that collection is readonly.
Attempt #2 Replace ServerVariables with my own instance
var request = HttpContext.Current.Request;
var requestType = request.GetType();
var variables = requestType.GetField("_serverVariables", BindingFlags.Instance | BindingFlags.NonPublic);
variables.SetValue(request, new NameValueCollection
{
{ "MY_CUSTOM_VAR", "value" }
});
Failed with error that it's not possible to cast NameValueCollection to HttpServerVarsCollection. That's because HttpServerVarsCollection is actually a internal class so I couldn't either to make an instance of it or cast to it.
So the question is - How can I mock ServerVariables or insert value there? Thanks
This is exactly the case where you should refactor your code.
Example of refactored code:
In your test:
Of course, you can extract the method to a separate dependency altogether.