Title: Mocking Requirements for TryUpdateModel in ASP.Net RC1
Tags: asp.net-mvc;unit-testing;mocking;updatemodel
Question: I am in the process of writing some unit tests for my controllers in RC1. Here is the
controller's public signature I'm testing:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult AcceptColleague()
The implementation inside the AcceptColleague uses the TryUpdateModel(colleague) method of populating the Colleague object from the form fields. However, I'm running into a "Object reference not set to an instance of an object" error on the TryUpdateModel line while trying to unit test the method.
Here is my unit test code:
// definition
HomeController controller = new HomeController();
IColleagueRepository fakeColleagueRepo = MockRepository.GenerateMock<IColleagueRepository&gt;();
Colleague requestedColleauge = new Colleague();
EmployeeInfo currentUser = new EmployeeInfo();
HttpContextBase fakeHttpContext = MockRepository.GenerateMock<HttpContextBase&gt;();
HttpRequestBase fakeHttpRequest = MockRepository.GenerateMock<HttpRequestBase&gt;();
ControllerContext fakeContext = MockRepository.GenerateMock<ControllerContext&gt;(fakeHttpContext, new RouteData(), controller);
NameValueCollection fakeForm = new NameValueCollection();
// expectations
fakeColleagueRepo.Expect(c =&gt; c.Read(1234)).Return(requestedColleauge);
fakeColleagueRepo.Expect(c =&gt; c.Update(requestedColleauge));
fakeColleagueRepo.Expect(c =&gt; c.Add(new Colleague())).IgnoreArguments().Constraints(Is.NotNull());
fakeContext.Expect(cx =&gt; cx.HttpContext).Return(fakeHttpContext);
fakeHttpContext.Expect(hcx =&gt; hcx.Request).Return(fakeHttpRequest);
fakeHttpRequest.Expect(hr =&gt; hr.Form).Return(fakeForm);
// setup
controller.ColleagueRepository = fakeColleagueRepo;
controller.ControllerContext = fakeContext;
requestedColleauge.TargetEmployeeInfoId = 123456;
requestedColleauge.GeneratedEmployeeInfoId = 654321;
currentUser.EmployeeInfoId = 123456;
fakeForm.Add("ColleagueId", "22222");
// action
RedirectToRouteResult result = controller.AcceptColleague() as RedirectToRouteResult;
// validation
Assert.IsNotNull(result, "AcceptColleague() did not return RedirectToRouteResult");
Am I missing something on the mocking or should I be using a different public signature like AcceptColleague(Colleague colleague) and then testing the ModelState.IsValid property?
If so, how don't see a way I can mock the read only ModelState property off of the controller?

Here is the accepted answer: TryUpdateModel and ModelState both require zero mocks in RC 1. The only thing that you have to supply is a ValueProvider. For that, you can use FormCollection.ToValueProvider().
You'll still need to mock your repository, but there is nothing that you need to mock in the framework for this functionality. Try this:
FormCollection fakeForm = new FormCollection();
fakeForm.Add("ColleagueId", "22222");
controller.ValueProvider = fakeForm.ToValueProvider();
// action
Note: No mocked HttpContext needed, unless your code requires it.
Comment for this answer: Craig, thanks a lot. I guess I missed that in the floating documentation out there. I works like a charm now.
Thanks again,
Comment for this answer: actually you need to provide a context, if you dont you get ArgumentNullException, Value cannot be null.Parameter name: controllerContext
Comment for this answer: Mvc 5.2.3 gave the Null Exception Omar described above.  controller.ControllerContext = new ControllerContext(); Allows the unit test to progress for me.


{'source': 'StackExchangeDataset', 'subset': 'stackoverflow.com', 'metadata': {'AnswerCount': 1, 'CommentCount': 0, 'ContentLicense': 'CC BY-SA 3.0', 'CreationDate': '2009:00:02/09/09', 'FavoriteCount': None, 'PostTypeId': 1, 'Tags': '<asp.net-mvc><unit-testing><mocking><updatemodel>', 'Title': 'Mocking Requirements for TryUpdateModel in ASP.Net RC1', 'ViewCount': 2102, 'id': 530133, 'user_AboutMe': '', 'user_AccountId': 24484.0, 'user_DisplayName': 'Cole B', 'user_Reputation': 75.0, 'user_Views': 65.0, 'user_id': 62275.0}}