C# 在传统ASP.NET应用程序中进行单元测试以模拟HttpContext
我有一个方法:C# 在传统ASP.NET应用程序中进行单元测试以模拟HttpContext,c#,asp.net,unit-testing,httpcontext,C#,Asp.net,Unit Testing,Httpcontext,我有一个方法: public DataSet someMethod() { List a = someObj.getList(name, integerId); } 现在,integerId是通过HttpContext.Current.Session变量获得的。 我已经为该方法编写了一个单元测试。但是由于测试在web进程之外运行,HttpContext.Current.Session返回null,测试失败 有什么解决方法吗?您需要为您的测试注入一个假的HttpContext,理想情况下
public DataSet someMethod()
{
List a = someObj.getList(name, integerId);
}
现在,integerId是通过HttpContext.Current.Session
变量获得的。
我已经为该方法编写了一个单元测试。但是由于测试在web进程之外运行,HttpContext.Current.Session
返回null,测试失败
有什么解决方法吗?您需要为您的测试注入一个假的
HttpContext
,理想情况下是作为HttpContextBase
,这是一个可模拟但在其他方面相同的API
您可以将HttpContext
包装在HttpContextWrapper
中,以获得HttpContextBase
阅读控制反转的各种技术,并找到一种适合您的技术。首先,您必须初始化: 然后,您必须设置会话:(Necroskillz在中解释了执行此操作的方法) 以下代码段显示了它的工作原理:
[TestMethod]
public void TestMethod1()
{
HttpContext.Current = new HttpContext(new HttpRequest("", "http://blabla.com", "") {},
new HttpResponse(new StringWriter()));
HttpContext.Current.SetFakeSession();
HttpContext.Current.Session["foo"] = 1;
Assert.AreEqual(1, HttpContext.Current.Session["foo"]);
}
我想这个问题的懒散答案应该是:学会使用,但我会继续提供一些指导 类不太可能需要HttpContext中的所有内容。您没有指定如何计算
整数ID
,但假设它是当前会话状态的会话ID
的散列。您的类实际上需要的只是某种方法来获取特定的SessionId
;这不需要是一个完整的HttpContext
interface ICurrentSessionIdProvider
{
string SessionId { get; }
}
现在你们班有:
// Pull this from a constructor parameter so you can provide any implementation you want
private readonly ICurrentSessionIdProvider _sessionIdProvider;
public DataSet someMethod()
{
int integerId = _sessionIdProvider.SessionId.GetHashCode();
List a = someObj.getList(name, integerId);
}
现在,在单元测试中,模拟这种依赖关系变得很简单。像Moq和AutoFixture这样的工具甚至可以帮你,现在你的生活轻松愉快等等
当然,在实际应用程序中,您希望使用基于HttpContext的实现:
class HttpContextCurrentSessionIdProvider : ICurrentSessionIdProvider
{
// Pull this from a constructor parameter or however you see fit.
private readonly HttpContext _httpContext;
public SessionId => _httpContext.Current.Session.SessionId;
}
在经典的ASP.NET中模拟HttpContext是很困难的。我建议您将对HttpContext.Session的引用包装在自己的mockable类中。数据访问层不应该依赖于HttpContext对象。是的,理想情况下应该是这样。然而,为了做到这一点,我的项目中有大量代码需要重新分解。
// Pull this from a constructor parameter so you can provide any implementation you want
private readonly ICurrentSessionIdProvider _sessionIdProvider;
public DataSet someMethod()
{
int integerId = _sessionIdProvider.SessionId.GetHashCode();
List a = someObj.getList(name, integerId);
}
class HttpContextCurrentSessionIdProvider : ICurrentSessionIdProvider
{
// Pull this from a constructor parameter or however you see fit.
private readonly HttpContext _httpContext;
public SessionId => _httpContext.Current.Session.SessionId;
}