我想单元测试Controller对象的Initialize方法。 Initialize()方法基本上从请求对象的cookie集合中提取玩家的ID,并从数据库中检索当前的玩家对象。然后播放器对象存储在控制器对象的CurrentPlayer属性中。我有以下代码进行单元测试。该测试基本上是为控制器的Index()方法编写的:
[Test]
public void Index_ReturnsJsonResult ()
{
var _gameRepositoryMock = GameRepositoryCreator.Create (5);
var _formsAuthenticationMock = new Mock<IFormsAuthentication> ();
var _chooseOpponentController = new ChooseOpponentController (_gameRepositoryMock.Object, _formsAuthenticationMock.Object);
var cookie = new HttpCookie (cookieName);
cookie.Value = player.PlayerID + "_encrypted";
var cookies = new HttpCookieCollection ();
cookies.Add (cookie);
var httpRequestMock = new Mock<HttpRequestBase> ();
httpRequestMock.Setup (x => x.Cookies).Returns (cookies);
httpRequestMock.Setup (x => x.IsAuthenticated).Returns (true);
var httpContextMock = new Mock<HttpContextBase> ();
httpContextMock.Setup (x => x.Request).Returns (httpRequestMock.Object);
var rd = new RouteData ();
rd.Values.Add ("action", "Index");
rd.Values.Add ("controller", "ChooseOpponent");
var requestContext = new RequestContext (httpContextMock.Object, rd);
_formsAuthenticationMock.Setup (x => x.Decrypt (cookie.Value)).Returns (player.PlayerID + "");
(_chooseOpponentController as IController).Execute (requestContext);
Assert.IsNotNull (_chooseOpponentController.CurrentPlayer);
... // test other things for the Index () method
}
Index()方法声明为:
[Authorize, SavePlayerStatus(Order=2), CommitChanges(Order=1)]
public ActionResult Index ()
{ ... }
Initialize()方法成功执行但之后我得到一个异常,并带有以下消息:“对象引用未设置为对象的实例。”,堆栈跟踪如下所示:
at System.Web.Compilation.BuildManager.GetCacheKeyFromVirtualPath(VirtualPath virtualPath, Boolean& keyFromVPP)
at System.Web.Compilation.BuildManager.GetVPathBuildResultFromCacheInternal(VirtualPath virtualPath, Boolean ensureIsUpToDate)
at System.Web.Compilation.BuildManager.GetVPathBuildResultInternal(VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean throwIfNotFound, Boolean ensureIsUpToDate)
at System.Web.Compilation.BuildManager.GetVPathBuildResultWithNoAssert(HttpContext context, VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean throwIfNotFound, Boolean ensureIsUpToDate)
at System.Web.Compilation.BuildManager.GetVirtualPathObjectFactory(VirtualPath virtualPath, HttpContext context, Boolean allowCrossApp, Boolean throwIfNotFound)
at System.Web.Mvc.BuildManagerWrapper.System.Web.Mvc.IBuildManager.FileExists(String virtualPath)
at System.Web.Mvc.BuildManagerViewEngine.FileExists(ControllerContext controllerContext, String virtualPath)
at System.Web.Mvc.VirtualPathProviderViewEngine.GetPathFromGeneralName(ControllerContext controllerContext, List`1 locations, String name, String controllerName, String areaName, String cacheKey, String[]& searchedLocations)
at System.Web.Mvc.VirtualPathProviderViewEngine.GetPath(ControllerContext controllerContext, String[] locations, String[] areaLocations, String locationsPropertyName, String name, String controllerName, String cacheKeyPrefix, Boolean useCache, String[]& searchedLocations)
at System.Web.Mvc.VirtualPathProviderViewEngine.FindView(ControllerContext controllerContext, String viewName, String masterName, Boolean useCache)
at System.Web.Mvc.ViewEngineCollection.<>c__DisplayClassc.<FindView>b__b(IViewEngine e)
at System.Web.Mvc.ViewEngineCollection.Find(Func`2 lookup, Boolean trackSearchedPaths)
at System.Web.Mvc.ViewEngineCollection.FindView(ControllerContext controllerContext, String viewName, String masterName)
at System.Web.Mvc.ViewResult.FindView(ControllerContext context)
at System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult)
at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass1c.<InvokeActionResultWithFilters>b__19()
at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation)
at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass1c.<>c__DisplayClass1e.<InvokeActionResultWithFilters>b__1b()
at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult)
at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)
感谢任何帮助。
答案 0 :(得分:3)
通过调用Execute
,您实际上是在调用整个MVC管道。这包括尝试转到磁盘并查找视图文件的视图查找逻辑。失败的部分是未正确初始化的ASP.NET编译系统。
对于单元测试,您执行的太多了。我会写两个测试:一个验证Index方法做正确的事,一个验证Initialize方法做正确的事。其他一切(在动作方法之前调用Initialize的事实等)是你不应该担心的MVC管道。