>我正在测试一个MVC 3控制器,该控制器调用此类上的方法:
public class SessionVar
{
/// <summary>
/// Gets the session.
/// </summary>
private static HttpSessionState Session
{
get
{
if (HttpContext.Current == null)
throw new ApplicationException
("No Http Context, No Session to Get!");
return HttpContext.Current.Session;
}
}
public static T Get<T>(string key)
{
return Session[key] == null ? default(T) : (T)Session[key];
}
...
}
我的测试方法,遵循Hanselman博客的建议是:
[Test]
public void CanRenderEmployeeList()
{
_mockIEmployeeService.Setup(s => s.GetEmployees(StatusFilter.OnlyActive))
.Returns(BuildsEmployeeList().Where(e => e.IsApproved));
var httpContext = FakeHttpContext();
var target = _employeeController;
target.ControllerContext = new ControllerContext
(new RequestContext(httpContext, new RouteData()), target);
var result = target.Index();
Assert.IsNotNull(result);
Assert.IsInstanceOf<ViewResult>(result);
var viewModel = target.ViewData.Model;
Assert.IsInstanceOf<EmployeeListViewModel>(viewModel);
}
public static HttpContextBase FakeHttpContext()
{
var context = new Mock<HttpContextBase>();
var request = new Mock<HttpRequestBase>();
var response = new Mock<HttpResponseBase>();
var session = new Mock<HttpSessionStateBase>();
var server = new Mock<HttpServerUtilityBase>();
context.Setup(ctx => ctx.Request).Returns(request.Object);
context.Setup(ctx => ctx.Response).Returns(response.Object);
context.Setup(ctx => ctx.Session).Returns(session.Object);
context.Setup(ctx => ctx.Server).Returns(server.Object);
return context.Object;
}
但是我的测试一直失败,我得到:
CanRenderEmployeeListSystem.ApplicationException : No Http Context,
No Session to Get!
这是HttpContext.Current == null
时要抛出的异常消息
我只需要会话对象"存在",而不是存储在会话上的实际值。
你能告诉我我做错了什么吗?
谢谢。
从长远来看,如果你为 SessionVar 类创建一个接口,你会更快乐。 在运行时使用当前的实现(通过依赖关系注入)。 在测试期间插入模拟。 无需模拟所有这些 Http 运行时依赖项。
会话属性中的 HttpContext.Current 不受正在创建的模拟 HttpContextBase 的影响。 也就是说,简单地创建一个本地的HttpContextBase不会自动填充HttpContext.Current。 事实上,HttpContext和HttpContextBase实际上并不相关。 你必须使用HttpContextWrapper来统一它们。
因此,最好将 HttpContextWrapper 实现传递到类 SessionVar 中。 在下面的代码中,我已将您的方法和属性更改为实例级别,以便我们可以在构造函数中设置上下文。 如果没有上下文传递给构造函数,我们假设 HttpContext.Current,但您也可以将模拟实例传递给您的测试。
public class SessionVar
{
HttpContextWrapper m_httpContext;
public SessionVar(HttpContextWrapper httpContext = null)
{
m_httpContext = httpContext ?? new HttpContextWrapper(HttpContext.Current);
}
/// <summary>
/// Gets the session.
/// </summary>
private HttpSessionState Session
{
get
{
if (m_httpContext == null)
throw new ApplicationException("No Http Context, No Session to Get!");
return m_httpContext.Session;
}
}
public T Get<T>(string key)
{
return Session[key] == null ? default(T) : (T)Session[key];
}
...
}