aspnet / Mvc

[Archived] ASP.NET Core MVC is a model view controller framework for building dynamic web sites with clean separation of concerns, including the merged MVC, Web API, and Web Pages w/ Razor. Project moved to https://github.com/aspnet/AspNetCore
Apache License 2.0
5.62k stars 2.14k forks source link

Unit Test with TryUpdateModelAsync fails with argument null exception Parameter name: metadataProvider #8721

Closed rrjamesjr closed 5 years ago

rrjamesjr commented 5 years ago

Is this a Bug or Feature request?:

Bug

Steps to reproduce (preferably a link to a GitHub repo with a repro project):

` [HttpPatch("{id}")] [ProducesResponseType(typeof(IDictionary<string, string>), (int)HttpStatusCode.BadRequest)] [ProducesResponseType((int)HttpStatusCode.BadRequest)] [ProducesResponseType((int)HttpStatusCode.NotFound)] [ProducesResponseType((int)HttpStatusCode.NoContent)] [ProducesResponseType((int)HttpStatusCode.InternalServerError)] [Consumes(Constants.JsonPatch)]

    public async Task<IActionResult> Patch(int id, [FromBody, Required] JsonPatchDocument<MyDto> myDto)
    {
        try
        {
            var  original = new MyDto();
            myDto.ApplyTo(original);

            if(!await TryUpdateModelAsync<MyDto>(original))
            {
                return BadRequest(ModelState);
            }                
        }
        catch (Exception e)
        {
            logger.LogError(e, string.Empty);
            return StatusCode((int)HttpStatusCode.InternalServerError, e);
        }

        return NoContent();
    }`

Description of the problem:

The above code executes fine but when manual testing but my unit test method fails with argument null exception Parameter name: metadataProvider when calling TryUpdateModelAsync method.

Version of Microsoft.AspNetCore.Mvc or Microsoft.AspNetCore.App or Microsoft.AspNetCore.All:

Microsoft.AspNetCore.App version 2.1.1

mkArtakMSFT commented 5 years ago

@rrjamesjr, please share with us the project so we can repro the unit-test failure.

rrjamesjr commented 5 years ago

Here is the repo

https://github.com/rrjamesjr/Issue8721

mkArtakMSFT commented 5 years ago

@rrjamesjr, looks like you haven't properly configured the ValueProviderFactories of the ControllerContext for the controller being tested: image

The ControllerBase.TryUpdateModelAsync method delegates the work to https://github.com/aspnet/Mvc/blob/bf8058da25ac245c5348c04999a0d909fb7df037/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/ModelBindingHelper.cs#L206 which in turn requires the modelMetadataProvider to be available.

@pranavkm, do we have a sample which would showcase how to do this properly?

pranavkm commented 5 years ago

If you'd like to unit test your controller action, I'd go the route of stubbing ControllerBase.TryUpdateModelAsync to verify if it does the right thing. If you're looking for an integration style test where the framework method executes as is, https://docs.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-2.1 has pretty detailed documentation on how you'd set this up.

rrjamesjr commented 5 years ago

Thanks...just mocked the controller and stubbed the method as suggested