我很新的測試和嘲笑,我想寫一個測試,以確保我的驗證邏輯正確設置ModelState錯誤。模擬MVC ControllerContext請求的問題
我所看到的是,controller.ControllerContext.HttpContext.Request設爲我第一次檢查,但在此之後,請求爲空每次。
這導致在MVC源* ValueProviderDictionary *類的PopulateDictionary方法一個空引用異常,因爲請求對象被訪問,該方法中多次而不確保請求不爲空。
我將幾種技術和幫手都粘在了一起,這些技巧和幫手是在研究如何克服迄今爲止遇到的一些問題的時候發現的,因此在這一點上我有點不確定我可能在哪裏介紹了該問題。
我在這裏使用模擬對象不正確嗎?
失敗的測試
//Test
public void Test_FooController_OnActionExecuting_ShouldMapStateToAFooModel()
{
//Arrange
DataAccessFactoryMocks.MockAllDaos();
var controller = new FooController();
var testFormCollection = new NameValueCollection();
testFormCollection.Add("foo.CustomerID", "3");
testFormCollection.Add("_fooForm", SerializationUtils.Serialize(new FooModel()));
var mockHttpContext = new MockHttpContext(controller, "POST", testFormCollection, null);
//Accessor used to run the protected OnActionExecuting method in my controller
var accessor = new FooControllerAccessor(controller);
//Request is set, assertion passes
Assert.IsNotNull(controller.ControllerContext.HttpContext.Request.Form);
//Request is null when accessing the property a second time, assertion fails
Assert.IsNotNull(controller.ControllerContext.HttpContext.Request.QueryString);
//Act
accessor.OnActionExecuting(new ActionExecutingContext(controller.ControllerContext, MockRepository.GenerateStub<ActionDescriptor>(), new Dictionary<string, object>()));
//Assert
Assert.That(controller.ModelState.IsValid == false);
}
測試助手
//Test helper to create httpcontext and set controller context accordingly
public class MockHttpContext
{
public HttpContextBase HttpContext { get; private set; }
public HttpRequestBase Request { get; private set; }
public HttpResponseBase Response { get; private set; }
public RouteData RouteData { get; private set; }
public MockHttpContext(Controller onController)
{
//Setup the common context components and their relationships
HttpContext = MockRepository.GenerateMock<HttpContextBase>();
Request = MockRepository.GenerateMock<HttpRequestBase>();
Response = MockRepository.GenerateMock<HttpResponseBase>();
//Setup the context, request, response relationship
HttpContext.Stub(c => c.Request).Return(Request);
HttpContext.Stub(c => c.Response).Return(Response);
Request.Stub(r => r.Cookies).Return(new HttpCookieCollection());
Response.Stub(r => r.Cookies).Return(new HttpCookieCollection());
Request.Stub(r => r.QueryString).Return(new NameValueCollection());
Request.Stub(r => r.Form).Return(new NameValueCollection());
//Apply the context to the suppplied controller
var rc = new RequestContext(HttpContext, new RouteData());
onController.ControllerContext = new ControllerContext(rc, onController);
}
public MockHttpContext(Controller onController, string httpRequestType, NameValueCollection form, NameValueCollection querystring)
{
//Setup the common context components and their relationships
HttpContext = MockRepository.GenerateMock<HttpContextBase>();
Request = MockRepository.GenerateMock<HttpRequestBase>();
Response = MockRepository.GenerateMock<HttpResponseBase>();
//Setup request type based on parameter value
Request.Stub(r => r.RequestType).Return(httpRequestType);
//Setup the context, request, response relationship
HttpContext.Stub(c => c.Request).Return(Request);
HttpContext.Stub(c => c.Response).Return(Response);
Request.Stub(r => r.Cookies).Return(new HttpCookieCollection());
Response.Stub(r => r.Cookies).Return(new HttpCookieCollection());
Request.Stub(r => r.QueryString).Return(querystring);
Request.Stub(r => r.Form).Return(form);
//Apply the context to the suppplied controller
var rc = new RequestContext(HttpContext, new RouteData());
onController.ControllerContext = new ControllerContext(rc, onController);
}
}
工作測試使用MvcContrib.TestHelper
public void Test_FooController_OnActionExecuting_ShouldMapStateToAFooModel()
{
//Arrange
DataAccessFactoryMocks.MockAllDaos();
TestControllerBuilder builder = new TestControllerBuilder();
builder.Form.Add("fooModel.CustomerID", "3");
builder.HttpContext.Request.Stub(r => r.RequestType).Return("POST");
FooController controller = builder.CreateController<FooController>();
var accessor = new FooControllerAccessor(controller);
//Act
accessor.OnActionExecuting(new ActionExecutingContext(controller.ControllerContext, MockRepository.GenerateStub<ActionDescriptor>(), new Dictionary<string, object>()));
//Assert
Assert.IsFalse(controller.ModelState.IsValid);
}
謝謝,我會考慮他們,因爲我最終會喜歡爲每個測試消除所有這些設置。儘管如此,我仍然不明白爲什麼房產被清理,我想寫一些冗長的測試來幫助我理解發生的事情。 TestHelper似乎隱藏了很多我認爲有益於理解的內部工作。 – jjr2527 2009-09-14 17:28:32
因爲當你定義期望時,你需要指定.Repeat.Any() – 2009-09-14 17:59:29
我使用TestHelper工作。 .Repeat.Any()仍然沒有修復原始測試,所以我必須仍然做錯了什麼。我很滿意什麼出來。上面更新的代碼。 – jjr2527 2009-09-14 18:50:01