Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test model binder in ASP.Net MVC 6?

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?

like image 438
Chad Avatar asked Feb 27 '16 19:02

Chad


People also ask

How do you bind a model to view in MVC?

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.

Can you unit test controllers?

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.

How can we use a custom model binder in asp net core?

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.


1 Answers

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
}
like image 149
James Sampica Avatar answered Oct 21 '22 23:10

James Sampica