使用 HttpContext.Application 进行单元测试 [英] Unit testing with HttpContext.Application
问题描述
我正在尝试对一些从 HttpContext.Current.Application
读取值的代码进行单元测试,但它一直失败,因为它无法检索该值.
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.
我尝试创建自己的 HttpContext
,将 HttpContext.Current
设置为它,然后向其写入值,但它似乎没有存储新值.
I've tried creating my own HttpContext
, setting HttpContext.Current
to it, then writing values to it but it does not seem to store the new values.
代码引用HttpContext.Current.Application
public static void UpdateApplicationVariable(string keyToUpdate, object toSave)
{
HttpContext.Current.Application.Lock();
HttpContext.Current.Application[keyToUpdate] = toSave;
HttpContext.Current.Application.UnLock();
}
public static object GetApplicationVariable(string keyToReturn)
{
return HttpContext.Current.Application[keyToReturn];
}
设置代码
HttpContext.Current = new HttpContext(
new HttpRequest(null, "http://tempuri.org", null),
new HttpResponse(null)
);
UpdateApplicationVariable("GeneralSettings", new GeneralSettings()
{
NumberDecimalPlaces = 2
});
//settings is null
GeneralSettings settings = GetApplicationVariable("GeneralSettings") as GeneralSettings;
推荐答案
不要模拟 HttpContext!!!他不喜欢被人嘲笑!
Don't mock HttpContext!!!! He doesn't like to be mocked!
相反,弄清楚您想要实现的功能是什么,并围绕它设计一个抽象.这将使您的代码更具可测试性,因为它与 HttpContext
的耦合不是那么紧密.
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; }
}
并且在您的代码中引用 HttpContext.Current.Application
可以更改...
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];
}
}
具体版本将包含访问HttpContext
所需的实际代码.像……
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();
}
}
}
现在在用于测试的代码设置中,您可以通过使用抽象的模拟、伪造或存根版本完全放弃 HttpContext...
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.
这篇关于使用 HttpContext.Application 进行单元测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!