Unit testing with HttpContext.Application

前端 未结 1 1857
终归单人心
终归单人心 2021-01-26 00:27

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

1条回答
  •  有刺的猬
    2021-01-26 00:58

    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 Application = new Dictionary();
            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.

    0 讨论(0)
提交回复
热议问题