我正在为MVC 5 Web应用程序编写单元测试。我从测试中 mock 了HttpContext.Current
。
当运行以下代码形式测试httpSessionStateAfter
throw
仅当我运行单元测试时才会发生这种情况。当应用程序运行时,此工作正常。
我正在将Nunit 2.6.3与reshaper测试运行程序一起使用。
var httpSessionStateBefour = System.Web.HttpContext.Current.Session;
var Person= await Db.Persons.FirstOrDefaultAsync();
var httpSessionStateAfter = System.Web.HttpContext.Current.Session;
如何克服这个问题?
这就是我模拟HttpContext的方式
HttpContext.Current = Fakes.FakeHttpContext();
HttpContext.Current.Session.Add("IsUserSiteAdmin", true);
HttpContext.Current.Session.Add("CurrentSite", null);
public static class Fakes
{
public static HttpContext FakeHttpContext()
{
var httpRequest = new HttpRequest("", "http://stackoverflow/", "");
var stringWriter = new StringWriter();
var httpResponce = new HttpResponse(stringWriter);
var httpContext = new HttpContext(httpRequest, httpResponce);
var sessionContainer = new HttpSessionStateContainer("id", new SessionStateItemCollection(),
new HttpStaticObjectsCollection(), 10, true,
HttpCookieMode.AutoDetect,
SessionStateMode.InProc, false);
httpContext.Items["AspSession"] = typeof (HttpSessionState).GetConstructor(
BindingFlags.NonPublic | BindingFlags.Instance,
null, CallingConventions.Standard,
new[] {typeof (HttpSessionStateContainer)},
null)
.Invoke(new object[] {sessionContainer});
return httpContext;
}
}
最佳答案
HttpContext.Current
被认为是一个非常糟糕的属性。它不会在ASP.NET主页之外运行。 修复代码的最佳方法是停止查看此属性,并找到一种方法将其与正在测试的代码隔离。 例如,您可以创建一个表示当前 session 数据的接口(interface),并通过需要HTTP上下文的实现将该接口(interface)公开给您正在测试的组件。
根本问题在于HttpContext.Current
的工作方式。该属性在ASP.NET框架中是“神奇的”,因为它对于请求-响应操作是唯一的,但是在执行需要时在线程之间跳转-在线程之间有选择地共享。
当您在ASP.NET处理管道之外使用HttpContext.Current
时,魔术就消失了。当您像使用异步编程样式一样在此处切换线程时,继续后该属性为null
。
如果您绝对不能更改代码以消除对HttpContext.Current
的硬依赖性,则可以利用本地上下文来作弊此测试:声明连续性时,本地范围内的所有变量都可用于连续性上下文。
// Bring the current value into local scope.
var context = System.Web.HttpContext.Current;
var httpSessionStateBefore = context.Session;
var person = await Db.Persons.FirstOrDefaultAsync();
var httpSessionStateAfter = context.Session;
需要明确的是,对于您当前的情况,这只会起作用。如果在另一个作用域之前在此之前引入
await
,则该代码将突然再次中断;这是一个简单而又肮脏的答案,我鼓励您忽略并寻求一个更可靠的解决方案。关于c# - HttpContext.Current在等待后为null(仅在单元测试中),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26118756/