Reputation: 7997
I found the following post which describes how to test a custom model binder:
https://stackoverflow.com/a/55387164/155899
However, this tests an individual model binder. Ideally I'd like to be able to register all of my binders and test that the appropriate model was bound. This is how I would've achieved what I'm looking for in ASP.NET MVC:
// Register the model binders
ModelBinders.Binders[typeof(DateTime)] = new DateTimeModelBinder();
...
var values = new NameValueCollection {
{ "Foo", "1964/12/02 12:00:00" }
};
var controllerContext = CreateControllerContext(); // Utility method
var bindingContext = new ModelBindingContext() {
ModelName = "Foo",
ValueProvider = new NameValueCollectionValueProvider(values, null)
};
var binder = ModelBinders.Binders.GetBinder(typeof(DateTime));
var result = (DateTime)binder.BindModel(controllerContext, bindingContext);
Not only does this allow me to test the result of my model binder but it also makes sure the correct model binder is selected.
I'd appreciate it if someone could help. Thanks
Upvotes: 5
Views: 3381
Reputation: 7997
I've managed to put something together. Thanks to @HereticMonkey for the link which helped me out.
[Fact]
public async Task Test() {
// Arrange
var services = new ServiceCollection();
services.AddSingleton<ILoggerFactory, NullLoggerFactory>();
services.AddSingleton<ObjectPoolProvider, DefaultObjectPoolProvider>();
services.AddMvc(o => {
o.ModelBinderProviders.Insert(0, new DateTimeModelBinderProvider());
});
var serviceProvider = services.BuildServiceProvider();
var options = serviceProvider.GetService<IOptions<MvcOptions>>();
var compositeDetailsProvider = new DefaultCompositeMetadataDetailsProvider(new List<IMetadataDetailsProvider>());
var metadataProvider = new DefaultModelMetadataProvider(compositeDetailsProvider);
var modelBinderFactory = new ModelBinderFactory(metadataProvider, options, serviceProvider);
var parameterBinder = new ParameterBinder(
metadataProvider,
modelBinderFactory,
new Mock<IObjectModelValidator>().Object,
options,
NullLoggerFactory.Instance);
var parameter = new ParameterDescriptor() {
Name = "parameter",
ParameterType = typeof(DateTime)
};
var controllerContext = new ControllerContext() {
HttpContext = new DefaultHttpContext() {
RequestServices = serviceProvider // You must set this otherwise BinderTypeModelBinder will not resolve the specified type
},
RouteData = new RouteData()
};
var modelMetadata = metadataProvider.GetMetadataForType(parameter.ParameterType);
var formCollection = new FormCollection(new Dictionary<string, StringValues>() {
{ "Foo", new StringValues("1964/12/02 12:00:00") }
});
var valueProvider = new FormValueProvider(BindingSource.Form, formCollection, CultureInfo.CurrentCulture);
var modelBinder = modelBinderFactory.CreateBinder(new ModelBinderFactoryContext() {
BindingInfo = parameter.BindingInfo,
Metadata = modelMetadata,
CacheToken = parameter
});
// Act
var modelBindingResult = await parameterBinder.BindModelAsync(
controllerContext,
modelBinder,
valueProvider,
parameter,
modelMetadata,
value: null);
// Assert
Assert.True(modelBindingResult.IsModelSet);
}
Upvotes: 6