I'm trying to write a unit test for a custom model binder in ASP.Net MVC 6. It seems simple enough. The model binder has a single BindModelAsync
method which takes a ModelBindingContext
parameter.
In my unit test, I'm trying to figure out how to fake the ModelBindingContext
. At first, I thought I could use the default constructor and set the properties on the object that I need. This works for all of the properties except ModelType
which is not settable.
I then looked at the static ModelBindingContext.CreateBindingContext
but it takes a bunch of scary looking parameters. Looking at how some of the model binding tests within the MVC repo are written, it seems like it is not possible for me to mock the ModelBindingContext.ModelType
(unless maybe I copy/paste those 6 classes from Microsoft.AspNetCore.Mvc.TestCommon).
Is there something simple/easy I am missing?
Step 1: Open the VS 2019 and select the ASP.NET core web application. Step 2: Select the template of the web application (MVC). Step 3: Go to the home controller and student basic type binding. Step 5: Now, press f5 and run the solution.
When unit testing controller logic, only the contents of a single action are tested, not the behavior of its dependencies or of the framework itself. Set up unit tests of controller actions to focus on the controller's behavior. A controller unit test avoids scenarios such as filters, routing, and model binding.
Model binding allows controller actions to work directly with model types (passed in as method arguments), rather than HTTP requests. Mapping between incoming request data and application models is handled by model binders.
I've had some success in getting it working for some simple form and query string values. AspNetCore.Mvc v1.1.3
private static DefaultModelBindingContext GetBindingContext(IValueProvider valueProvider, Type modelType)
{
var metadataProvider = new EmptyModelMetadataProvider();
var bindingContext = new DefaultModelBindingContext
{
ModelMetadata = metadataProvider.GetMetadataForType(modelType),
ModelName = modelType.Name,
ModelState = new ModelStateDictionary(),
ValueProvider = valueProvider,
};
return bindingContext;
}
Using a query string provider
[TestMethod]
public async Task QueryStringValueProviderTest()
{
var binder = new MyModelBinder();
var queryCollection = new QueryCollection(
new Dictionary<string, StringValues>()
{
{ "param1", new StringValues("1") },
{ "param2", new StringValues("2") },
});
var vp = new QueryStringValueProvider(BindingSource.Query, queryCollection, CultureInfo.CurrentCulture);
var context = GetBindingContext(vp, typeof(MyModel));
await binder.BindModelAsync(context);
var resultModel = context.Result.Model as MyModel;
//TODO Asserts
}
Using a form collection provider
[TestMethod]
public async Task FormValueProviderTest()
{
var binder = new MyModelBinder();
var formCollection = new FormCollection(
new Dictionary<string, StringValues>()
{
{ "param1", new StringValues("1") },
{ "param2", new StringValues("2") }
});
var vp = new FormValueProvider(BindingSource.Form, formCollection, CultureInfo.CurrentCulture);
var context = GetBindingContext(vp, typeof(MyModel));
await binder.BindModelAsync(context);
var resultModel = context.Result.Model as MyModel;
//TODO asserts
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With