I\'m trying to unit test some code that reads a value from HttpContext.Current.Application
but it keeps failing because it can\'t retrieve the value.
I\'ve
Don't mock HttpContext!!!! He doesn't like to be mocked!
Instead figure out what is the functionality you would like to achieve and design an abstraction around that. This will allow for your code to be more testable as it is not so tightly coupled to HttpContext
.
public interface IApplicationSettings {
object this[string key] { get; set; }
}
And in your Code referencing the HttpContext.Current.Application
can be changed...
public static class SomeUtilityClass {
public static IApplicationSettings Application {get;set;}
public static void UpdateApplicationVariable(string keyToUpdate, object toSave)
{
Application[keyToUpdate] = toSave;
}
public static object GetApplicationVariable(string keyToReturn)
{
return Application[keyToReturn];
}
}
The concrete version would have the actual code you need to access HttpContext
. Something like...
public class ConcreteApplicationSettings : IApplicationSettings {
public string this[string keyToReturn] {
get {
return HttpContext.Current.Application[keyToReturn];
}
set {
HttpContext.Current.Application.Lock();
HttpContext.Current.Application[keyToUpdate] = value;
HttpContext.Current.Application.UnLock();
}
}
}
Now in your Code setup for testing you can forego the HttpContext completely by using a mocked,faked or stubbed version of your abstraction...
[TestClass]
public class ApplicationVariablesTests {
public class FakeApplicationSettings : IApplicationSettings {
Dictionary<string,object> Application = new Dictionary<string,object>();
public string this[string keyToReturn] {
get { return Application[keyToReturn]; }
set { Application[keyToUpdate] = value; }
}
}
[TestMethod]
public void Should_Update_General_Settings() {
//Arrange
SomeUtilityClass.Application = new FakeApplicationSettings();
SomeUtilityClass.UpdateApplicationVariable("GeneralSettings", new GeneralSettings()
{
NumberDecimalPlaces = 2
});
//Act
GeneralSettings settings = SomeUtilityClass.GetApplicationVariable("GeneralSettings") as GeneralSettings;
//Assert
Assert.IsNotNull(settings);
Assert.AreEqual(2, settings.NumberDecimalPlaces);
}
}
In production code you will use the actual version instead of a fake. This also allows you to swap in and out different versions in the fusture if you decide to use something else to store your variables.