我尝试设置会话变量以运行某些单元测试时未成功。当我尝试设置会话变量时,我不断收到“System.NullReferenceException:对象引用未设置为对象实例”的错误。
这是我正在建立的测试:
[TestMethod]
public void MyMethod()
{
//Arrange
int id = 12345;
string action = "A";
string comment = "";
string user = "user";
var controller = new MyController();
//Act
controller.Session["altUser"] = user;
var result = controller.Process(id, action, comment);
//Assert
Assert.IsNotNull(result);
}
这是我的控制器:
[Authorize]
public class MyController : Controller
{
public ActionResult Process(int id, string action, string comment)
{
string userId = Session["altUser"].ToString();
//some other stuff that evaluates ID, Action, and Comment
}
}
但是,当我运行应用程序本身时,没有错误,应用程序正常运行。我确实理解,通过测试驱动开发,测试应该为实现铺平道路。我正在尝试对已经完成的应用程序进行单元测试。如果可能的话,既然应用程序有效,我想避免对我的实现进行任何更改,只需编写一个单元测试来支持我已经知道的内容。
答案 0 :(得分:8)
控制器从HttpContext
获取会话,这在单元测试中不存在,这就是失败的原因。
但是,您可以模拟HttpContext
并在其中放置模拟会话。
这样的东西可能会起作用(使用moq作为Mocking框架)
var mockControllerContext = new Mock<ControllerContext>();
var mockSession = new Mock<HttpSessionStateBase>();
mockSession.SetupGet(s => s["altUser"]).Returns("user");
mockControllerContext.Setup(p => p.HttpContext.Session).Returns(mockSession.Object);
var controller = new MyController();
controller.ControllerContext = mockControllerContext.Object;
你显然需要在模拟对象中填写你真正希望得到的细节。
您还可以从HttpSessionStateBase
和HttpContextBase
派生自己的类,并使用它们代替真实会话。
答案 1 :(得分:2)
没有勺子,呃,会话 - 当您执行单元测试时,ASP.NET runtine既未初始化也未运行。您应该分解代码之外的任何Session
依赖项,并使您需要的类和方法独立于ASP.NET的运行时功能进行单元测试。
答案 2 :(得分:0)
当您运行单元测试时,您没有通过Web服务器运行程序,因此无法访问任何HttpContext或ASP.NET会话,而当您通过VS中的调试运行程序时,正在使用内置的Visual Studio Web服务器,它使程序能够使用该会话。
Here是一篇文章,它将引导您完成ASP.NET会话及其工作原理。