2011-05-09 36 views
0

我试图按照typical pattern重写ControllerContext以模拟HttpContext。在我的情况下,我特别想测试HTTP POSTS,所以我需要模拟Request.Form。MVC嘲笑HttpContext,模型绑定错误

我尝试了所有在谷歌上找到的3种口味 - 与Moq,Rhino.Mocks和MVCContrib.TestHelpers。对于我的具体情况,我一直无法找到解决方案。

当我的控制器尝试模型绑定,我得到以下错误:

Object reference not set to an instance of an object. 
System.NullReferenceException: Object reference not set to an instance of an object. 
at Microsoft.Web.Infrastructure.DynamicValidationHelper.ValidationUtility.CollectionReplacer.GetUnvalidatedCollections(HttpContext context) 
at System.Web.Helpers.Validation.Unvalidated(HttpRequest request) 
at System.Web.Mvc.FormValueProviderFactory.<.ctor>b__0(ControllerContext cc) 
at System.Web.Mvc.FormValueProviderFactory.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) 
at eServices.Admin.Web.Controllers.User.UserController.Search() in UserController.cs: line 56 
at eServices.Admin.Specs.Controllers.when_the_user_controller_is_posted_the_manage_users_find_form.<.ctor>b__1() in UserControllerSpecs.cs: line 96 

这似乎表明,它是没有找到嘲笑的形式。下面是测试代码片段:

MoqHttpContext MoqHttpContext = new MoqHttpContext(); 
var sut = new UserController(
      UserRepository, 
      EmailService, 
      SessionProvider); 

var controllerContext = new ControllerContext 
     (new RequestContext(MoqHttpContext.GetHttpContext(), new RouteData()), sut); 
sut.ControllerContext = controllerContext; 

MoqHttpContext.FormData.Add("FindCriteria.SearchText", "searchText"); 
MoqHttpContext.FormData.Add("FindCriteria.AccountIsPending", "true"); 

sut.Search(); 

...

控制器:

[AcceptVerbs(HttpVerbs.Post)] 
    public ActionResult Search() 
    { 
     var manageUsersViewModel = new ManageUsersViewModel(); 
     TryUpdateModel(manageUsersViewModel); 

...

测试员额的任何意见或更好的解决方案?

回答

2

使用MvcContrib.TestHelper:是

// arrange 
var sut = new SomeController(); 
var tcb = new TestControllerBuilder(); 
tcb.InitializeController(sut); 
var formValues = new FormCollection() 
{ 
    { "FindCriteria.SearchText", "searchText" }, 
    { "FindCriteria.AccountIsPending", "true" }, 
}; 
sut.ValueProvider = formValues.ToValueProvider(); 

// act 
var actual = sut.Search(); 

// assert 
... 

Any ideas or better solutions for testing POSTs?

:使用TryUpdateModel而不是有你的控制器动作直接将视图模型参数:

[HttpPost] 
public ActionResult Search(ManageUsersViewModel model) 
{ 
    ... 
} 

然后在单元测试:

// arrange 
var sut = new SomeController(); 
var model = new ManageUsersViewModel 
{ 
    FindCriteria = new FindCriteria 
    { 
     SearchText = "searchText", 
     AccountIsPending = true 
    } 
}; 

// act 
var actual = sut.Search(model); 

// assert 
... 
+0

我在获取操作的会话中存储视图模型(从服务调用填充),然后在调用TryUpdateModel之前检索该视图模型的后操作中。因为我想在会话中保存从服务接收到的数据(或者将来可能会使用缓存),所以我依赖于TryUpdateModel。有没有办法通过动作参数的方式进行模型绑定,但是使用模型绑定可以工作的初始值,最初是从会话/缓存接收到的?希望这是有道理的 – jamiebarrow 2011-07-26 15:57:52