运行单元测试时出现以下错误: NullReferenceException未被usercode处理。 对象引用未设置为对象的实例。
不确定我哪里出错了。请指教。
我的SessionManager.cs类
public static int customerID
{
get
{
if (HttpContext.Current.Session != null &&
HttpContext.Current.Session[_customerID] != null)
{
return Convert.ToInt32(HttpContext.Current.Session[_customerID]);
}
else
{
throw new Ramsell.ExceptionManagement.RamsellException();
}
}
set
{
if (HttpContext.Current.Session == null) return;
HttpContext.Current.Session[_customerID] = value;
}
}
ParticipantController
public ActionResult Index()
{
int custId = Convert.ToInt32(SessionManager.customerID);
//code logic about participant lists
return View();
}
测试方法:
[TestMethod]
public void IndexTest()
{
ParticipantController pCTarget = new ParticipantController();
const int page = 1;
const string sortBy = "FirstName";
const bool ascending = true;
const string partname = "";
const int success = -1;
const string id = "";
var expected = typeof(ParticipantListViewModel);
ViewResult result = pCTarget.Index(page, sortBy, ascending, partname, success, id) as ViewResult;
Assert.AreEqual(expected, result.Model.GetType());
}
//这是我的模拟课程
public Mock<RequestContext> RoutingRequestContext { get; private set; }
public Mock<HttpContextBase> Http { get; private set; }
public Mock<HttpServerUtilityBase> Server { get; private set; }
public Mock<HttpResponseBase> Response { get; private set; }
public Mock<HttpRequestBase> Request { get; private set; }
public Mock<HttpSessionStateBase> Session { get; private set; }
public Mock<ActionExecutingContext> ActionExecuting { get; private set; }
public HttpCookieCollection Cookies { get; private set; }
public MockContext()
{
this.RoutingRequestContext = new Mock<RequestContext>(MockBehavior.Loose);
this.ActionExecuting = new Mock<ActionExecutingContext>(MockBehavior.Loose);
this.Http = new Mock<HttpContextBase>(MockBehavior.Loose);
this.Server = new Mock<HttpServerUtilityBase>(MockBehavior.Loose);
this.Response = new Mock<HttpResponseBase>(MockBehavior.Loose);
this.Request = new Mock<HttpRequestBase>(MockBehavior.Loose);
this.Session = new Mock<HttpSessionStateBase>(MockBehavior.Loose);
this.Cookies = new HttpCookieCollection();
this.RoutingRequestContext.SetupGet(c => c.HttpContext).Returns(this.Http.Object);
this.ActionExecuting.SetupGet(c => c.HttpContext).Returns(this.Http.Object);
this.Http.SetupGet(c => c.Request).Returns(this.Request.Object);
this.Http.SetupGet(c => c.Response).Returns(this.Response.Object);
this.Http.SetupGet(c => c.Server).Returns(this.Server.Object);
this.Http.SetupGet(c => c.Session).Returns(this.Session.Object);
this.Request.Setup(c => c.Cookies).Returns(Cookies);
var sessionContainer = new HttpSessionStateContainer("userID", new SessionStateItemCollection(),
new HttpStaticObjectsCollection(), 1, true,
HttpCookieMode.AutoDetect,
SessionStateMode.InProc, false);
this.Session.Setup(c => c.Add("AspSession", typeof(HttpSessionState).GetConstructor(
BindingFlags.NonPublic | BindingFlags.Instance,
null, CallingConventions.Standard,
new[] { typeof(HttpSessionStateContainer) },
null)
.Invoke(new object[] { sessionContainer })));
}
答案 0 :(得分:2)
当您为控制器编写单元测试时,您应该单独测试它 - 即应该模拟控制器的依赖性。因此,请确保您的控制器依赖于抽象而不是具体的SessionManager
实现(使您的类非静态并从您的经理类中提取ISessionManager
接口):
public interface ISessionManager
{
int CustomerID { get; set; }
}
public class HttpSessionManager : ISessionManager
{
// your current implementation goes here
}
然后模拟这个抽象并将其注入控制器(使用Moq的样本):
[TestMethod]
public void IndexTest()
{
var sessionManager = new Mock<ISessionManager>(); // Mock dependency
sessionManager.Setup(m => m.CustomerID).Returns(42);
const int page = 1;
const string sortBy = "FirstName";
const bool ascending = true;
const string partname = "";
const int success = -1;
const string id = "";
var expectedModelType = typeof(ParticipantListViewModel);
ParticipantController pCTarget =
new ParticipantController(sessionManager.Object); // Inject dependency
var view = pCTarget.Index(page, sortBy, ascending, partname, success, id)
as ViewResult;
sessionManager.VerifyGet(m => m.CustomerID); // Verify dependency was called
Assert.AreEqual(expectedModelType, view.Model.GetType());
}
这是控制器代码:
public class ParticipantController : Controller
{
private readonly ISessionManager _sessionManager;
public ParticipantController(ISessionManager sessionManager)
{
_sessionManager = sessionManager;
}
public ActionResult Index()
{
int custId = _sessionManager.CustomerID;
//code logic about participant lists
return View();
}
}
请注意,单元测试的目标是确保代码的每一小部分都按预期工作。如果你将依赖于测试中的其他单元,那么测试可能会失败有两个原因 - 你测试的单元表现不如预期,或者依赖项有问题你已经遇到了这种情况 - 控制器测试失败,因为会话管理器抛出异常。测试表明控制器的行为并不像预期的那样。这是真的吗?不 - 它的会话管理器表现不如预期。