我正在尝试伪造http上下文以测试Controller。我的环境是MVC 3和Moq 4。 到目前为止,我尝试了一些选项,包括:
一个。
var searchController = new MySearchController(_mockResolver.Object.Resolve<IConfiguration>());
var mockContext = new Mock<ControllerContext>();
searchController.ControllerContext = mockContext.Object;
var result = searchController.Render();
湾
var searchController = new MopSearchController(_mockResolver.Object.Resolve<IConfiguration>());
searchController.MockControllerContext();
var result = searchController.Render();
public static class MockHttpHelper
{
public static Mock<HttpContextBase> MockControllerContext(
this Controller controller, string path = null)
{
var mockHttpCtx = MockHttpHelper.MockHttpContext(path);
var requestCtx = new RequestContext(mockHttpCtx.Object, new RouteData());
var controllerCtx = new ControllerContext(requestCtx, controller);
controller.ControllerContext = controllerCtx;
return mockHttpCtx;
}
public static Mock<HttpContextBase> MockHttpContext(string path)
{
var mockHttpCtx = new Mock<HttpContextBase>();
var mockReq = new Mock<HttpRequestBase>();
mockReq.SetupGet(x => x.RequestType).Returns("GET");
mockReq.SetupGet(req => req.Form).Returns(new NameValueCollection());
mockReq.SetupGet(req => req.QueryString).Returns(new NameValueCollection());
mockHttpCtx.SetupGet(x => x.Request).Returns(mockReq.Object);
return mockHttpCtx;
}
}
这些都不起作用,我在下面得到了例外。有人能指出我的工作方向吗?我在网上围绕同一主题看到了不少问题,但考虑到日期(2008-2010的帖子)和MVC版本(即1和2),我觉得我错过了某些东西/或试图嘲笑更多比我在MVC3中需要的那样。
System.NullReferenceException : Object reference not set to an instance of an object.
at System.Web.Mvc.ChildActionValueProviderFactory.GetValueProvider(ControllerContext controllerContext)
at System.Web.Mvc.ValueProviderFactoryCollection.<>c__DisplayClassc.<GetValueProvider>b__7(ValueProviderFactory factory)
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList(IEnumerable`1 source)
at System.Web.Mvc.ValueProviderFactoryCollection.GetValueProvider(ControllerContext controllerContext)
at System.Web.Mvc.Controller.TryUpdateModel(TModel model)
由于
答案 0 :(得分:0)
是的,正如您所指出的那样,您真正缺少的是设置Controller的ValueProvider
。即使您将此控制器与Get操作但没有Post操作一起使用,Controller仍会在创建时实例化ValueProvider
,因此您需要在测试场景中执行相同的操作。这是我在测试控制器时使用的基类。我使用NBehave's NUnit wrapper进行单元测试,因此如果您愿意,请忽略SpecBase
引用
public abstract class MvcSpecBase<T> : SpecBase<T> where T : Controller
{
protected T Controller { get; set; }
protected string RelativePath = string.Empty;
protected string AbsolutePath = string.Empty;
protected void InitialiseController(T controller, NameValueCollection collection, params string[] routePaths)
{
Controller = controller;
var routes = new RouteCollection();
RouteConfig.RegisterRoutes(routes);
var httpContext = ContextHelper.FakeHttpContext(RelativePath, AbsolutePath, routePaths);
var context = new ControllerContext(new RequestContext(httpContext, new RouteData()), Controller);
var urlHelper = new UrlHelper(new RequestContext(httpContext, new RouteData()), routes);
Controller.ControllerContext = context;
Controller.ValueProvider = new NameValueCollectionValueProvider(collection, CultureInfo.CurrentCulture);
Controller.Url = urlHelper;
}
}
然后,在您的测试中,创建您的控制器,然后调用此行:
InitialiseController(controller, new FormCollection());