I've written some custom model binders (implementing IModelBinder) in our ASP.NET MVC application. I'm wondering what is a good approach to unittest them (binders)?
我在ASP.NET MVC应用程序中编写了一些自定义模型绑定器(实现IModelBinder)。我想知道什么是对它们进行单元测试的好方法(粘合剂)?
3 个解决方案
#1
12
I did it this way:
我是这样做的:
var formElements = new NameValueCollection() { {"FirstName","Bubba"}, {"MiddleName", ""}, {"LastName", "Gump"} };
var fakeController = GetControllerContext(formElements);
var valueProvider = new Mock<IValueProvider>();
var bindingContext = new ModelBindingContext(fakeController, valueProvider.Object, typeof(Guid), null, null, null, null);
private static ControllerContext GetControllerContext(NameValueCollection form) {
Mock<HttpRequestBase> mockRequest = new Mock<HttpRequestBase>();
mockRequest.Expect(r => r.Form).Returns(form);
Mock<HttpContextBase> mockHttpContext = new Mock<HttpContextBase>();
mockHttpContext.Expect(c => c.Request).Returns(mockRequest.Object);
return new ControllerContext(mockHttpContext.Object, new RouteData(), new Mock<ControllerBase>().Object);
}
And then I just passed in the bindingContext variable to the BindModel method of the object that implements the IModelBinder interface.
然后我将bindingContext变量传递给实现IModelBinder接口的对象的BindModel方法。
#2
12
Here's a simple no-mocks way I wrote for you on my blog assuming you use the ValueProvider and not the HttpContext: http://www.hanselman.com/blog/SplittingDateTimeUnitTestingASPNETMVCCustomModelBinders.aspx
这是我在博客上为您写的一个简单的无模式方法,假设您使用的是ValueProvider而不是HttpContext:http://www.hanselman.com/blog/SplittingDateTimeUnitTestingASPNETMVCCustomModelBinders.aspx
[TestMethod]
public void DateTime_Can_Be_Pulled_Via_Provided_Month_Day_Year_Hour_Minute_Second_Alternate_Names()
{
var dict = new ValueProviderDictionary(null) {
{ "foo.month1", new ValueProviderResult("2","2",null) },
{ "foo.day1", new ValueProviderResult("12", "12", null) },
{ "foo.year1", new ValueProviderResult("1964", "1964", null) },
{ "foo.hour1", new ValueProviderResult("13","13",null) },
{ "foo.minute1", new ValueProviderResult("44", "44", null) },
{ "foo.second1", new ValueProviderResult("01", "01", null) }
};
var bindingContext = new ModelBindingContext() { ModelName = "foo", ValueProvider = dict };
DateAndTimeModelBinder b = new DateAndTimeModelBinder() { Month = "month1", Day = "day1", Year = "year1", Hour = "hour1", Minute = "minute1", Second = "second1" };
DateTime result = (DateTime)b.BindModel(null, bindingContext);
Assert.AreEqual(DateTime.Parse("1964-02-12 13:44:01"), result);
}
#3
3
dict could be refactored like this
dict可以像这样重构
FormCollection form = new FormCollection
{
{ "month1", "2" },
{ "day1", "12" },
{ "year1", "1964" },
{ "hour1", "13" },
{ "minute1", "44" },
{ "second1", "01" }
};
var bindingContext = new ModelBindingContext() { ModelName = "foo", ValueProvider = form.ToValueProvider() };
#1
12
I did it this way:
我是这样做的:
var formElements = new NameValueCollection() { {"FirstName","Bubba"}, {"MiddleName", ""}, {"LastName", "Gump"} };
var fakeController = GetControllerContext(formElements);
var valueProvider = new Mock<IValueProvider>();
var bindingContext = new ModelBindingContext(fakeController, valueProvider.Object, typeof(Guid), null, null, null, null);
private static ControllerContext GetControllerContext(NameValueCollection form) {
Mock<HttpRequestBase> mockRequest = new Mock<HttpRequestBase>();
mockRequest.Expect(r => r.Form).Returns(form);
Mock<HttpContextBase> mockHttpContext = new Mock<HttpContextBase>();
mockHttpContext.Expect(c => c.Request).Returns(mockRequest.Object);
return new ControllerContext(mockHttpContext.Object, new RouteData(), new Mock<ControllerBase>().Object);
}
And then I just passed in the bindingContext variable to the BindModel method of the object that implements the IModelBinder interface.
然后我将bindingContext变量传递给实现IModelBinder接口的对象的BindModel方法。
#2
12
Here's a simple no-mocks way I wrote for you on my blog assuming you use the ValueProvider and not the HttpContext: http://www.hanselman.com/blog/SplittingDateTimeUnitTestingASPNETMVCCustomModelBinders.aspx
这是我在博客上为您写的一个简单的无模式方法,假设您使用的是ValueProvider而不是HttpContext:http://www.hanselman.com/blog/SplittingDateTimeUnitTestingASPNETMVCCustomModelBinders.aspx
[TestMethod]
public void DateTime_Can_Be_Pulled_Via_Provided_Month_Day_Year_Hour_Minute_Second_Alternate_Names()
{
var dict = new ValueProviderDictionary(null) {
{ "foo.month1", new ValueProviderResult("2","2",null) },
{ "foo.day1", new ValueProviderResult("12", "12", null) },
{ "foo.year1", new ValueProviderResult("1964", "1964", null) },
{ "foo.hour1", new ValueProviderResult("13","13",null) },
{ "foo.minute1", new ValueProviderResult("44", "44", null) },
{ "foo.second1", new ValueProviderResult("01", "01", null) }
};
var bindingContext = new ModelBindingContext() { ModelName = "foo", ValueProvider = dict };
DateAndTimeModelBinder b = new DateAndTimeModelBinder() { Month = "month1", Day = "day1", Year = "year1", Hour = "hour1", Minute = "minute1", Second = "second1" };
DateTime result = (DateTime)b.BindModel(null, bindingContext);
Assert.AreEqual(DateTime.Parse("1964-02-12 13:44:01"), result);
}
#3
3
dict could be refactored like this
dict可以像这样重构
FormCollection form = new FormCollection
{
{ "month1", "2" },
{ "day1", "12" },
{ "year1", "1964" },
{ "hour1", "13" },
{ "minute1", "44" },
{ "second1", "01" }
};
var bindingContext = new ModelBindingContext() { ModelName = "foo", ValueProvider = form.ToValueProvider() };