我正在尝试进行单元测试,其中还包括Moq版本4.5.9。 简单地说,我只想像在Mvc控制器中那样获得Url.Action。 这就是我所做的:
var Cntrlr = new ErrorController();
var HttpCnt = new Mock<HttpContextHelper>(Utility.FakeHttpContext);
var UrlHelperMock = new Mock<UrlHelper>(HttpCnt.Object.ContextRequest.RequestContext);
Cntrlr.Url = UrlHelperMock.Object;
var RedirectUrl = Cntrlr.Url.Action("Index", "Error", new { errorName = "NotSupport" });
另外,如果你必须知道,FakeHttpContext是这样的:
public static HttpContext FakeHttpContext
{
get
{
var HttpRequest = new HttpRequest("", "http://localhost/", "");
var StringWriter = new StringWriter();
var HttpResponse = new HttpResponse(StringWriter);
var HttpContext = new HttpContext(HttpRequest, HttpResponse);
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;
}
}
为什么RedirectUrl会返回Null?你能帮忙吗?
答案 0 :(得分:1)
Url.Action
在这种情况下返回null
的原因是因为您已经模拟了UrlHelper
,但是您还没有定义当您的代码调用{{1}时应该发生的事情你的模拟方法。
UrlHelper.Action
Url.Action
我们的想法是,您应该在特定条件下测试您的代码,而不关心您是在幕后调用真实的还是假的var Cntrlr = new ErrorController();
var UrlHelperMock = new Mock<UrlHelper>();
UrlHelperMock
.Setup(x => x.Action(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<object>()))
.Returns("/Error/Index/NotSupport");
Cntrlr.Url = UrlHelperMock.Object;
var RedirectUrl = Cntrlr.Url.Action("Index", "Error", new { errorName = "NotSupport" });
。您应该只模拟最低限度以使测试工作,因此在这种情况下创建假的Url.Action
或HttpContext
是过度的。
注意:您应该假设MVC框架已经有测试以确保
RequestContext
功能。而且,您应该unit test your routes确保Url.Action
在所有情况下都会返回正确的网址。但这是单元测试的另一个问题。
答案 1 :(得分:0)
我找到了答案here。
public static class AutoMockContainer
{
public static AutoMock Create()
{
var autoMock = new AutoMock();
var httpContext = Substitute.For<HttpContextBase>();
autoMock.Provide(httpContext);
var server = Substitute.For<HttpServerUtilityBase>();
httpContext.Server.Returns(server);
var request = Substitute.For<HttpRequestBase>();
var parameters = new NameValueCollection();
request.Params.Returns(parameters);
var formParameters = new NameValueCollection();
request.Form.Returns(formParameters);
var qsParameters = new NameValueCollection();
request.QueryString.Returns(qsParameters);
var headers = new NameValueCollection();
headers.Add("Host", "localhost");
request.Headers.Returns(headers);
request.AppRelativeCurrentExecutionFilePath.Returns("~/");
request.ApplicationPath.Returns("/");
request.Url.Returns(new Uri("http://localhost/"));
request.Cookies.Returns(new HttpCookieCollection());
request.ServerVariables.Returns(new NameValueCollection());
autoMock.Provide(request);
httpContext.Request.Returns(request);
var response = Substitute.For<HttpResponseBase>();
response.Cookies.Returns(new HttpCookieCollection());
response.ApplyAppPathModifier(Arg.Any<string>()).Returns(a => a.Arg<string>());
autoMock.Provide(response);
httpContext.Response.Returns(response);
var routeData = new RouteData();
var requestContext = Substitute.For<RequestContext>();
requestContext.RouteData = routeData;
requestContext.HttpContext = httpContext;
autoMock.Provide(requestContext);
var actionExecutingContext = Substitute.For<ActionExecutingContext>();
actionExecutingContext.HttpContext.Returns(httpContext);
actionExecutingContext.RouteData.Returns(routeData);
actionExecutingContext.RequestContext = requestContext;
autoMock.Provide(actionExecutingContext);
var actionExecutedContext = Substitute.For<ActionExecutedContext>();
actionExecutedContext.HttpContext.Returns(httpContext);
actionExecutedContext.RouteData.Returns(routeData);
actionExecutedContext.RequestContext = requestContext;
autoMock.Provide(actionExecutedContext);
var controller = Substitute.For<ControllerBase>();
autoMock.Provide(controller);
actionExecutingContext.Controller.Returns(controller);
var controllerContext = Substitute.For<ControllerContext>();
controllerContext.HttpContext = httpContext;
controllerContext.RouteData = routeData;
controllerContext.RequestContext = requestContext;
controllerContext.Controller = controller;
autoMock.Provide(controllerContext);
controller.ControllerContext = controllerContext;
var iView = Substitute.For<IView>();
autoMock.Provide(iView);
var viewDataDictionary = new ViewDataDictionary();
autoMock.Provide(viewDataDictionary);
var iViewDataContainer = Substitute.For<IViewDataContainer>();
iViewDataContainer.ViewData.Returns(viewDataDictionary);
autoMock.Provide(iViewDataContainer);
var textWriter = Substitute.For<TextWriter>();
autoMock.Provide(textWriter);
var viewContext = new ViewContext(controllerContext, iView, viewDataDictionary, new TempDataDictionary(), textWriter)
{
HttpContext = httpContext,
RouteData = routeData,
RequestContext = requestContext,
Controller = controller
};
autoMock.Provide(viewContext);
return autoMock;
}
public static T GetController<T>(this AutoMock autoMock) where T : Controller
{
var routes = new RouteCollection();
MyApplication.RegisterRoutes(routes);
var controller = autoMock.Resolve<T>();
controller.ControllerContext = autoMock.Resolve<ControllerContext>();
controller.Url = new UrlHelper(autoMock.Resolve<RequestContext>(), routes);
return controller;
}
}
初始化
var autoMock = AutoMockContainer.Create();
var controller = autoMock.GetController<HomeController>();