Как я могу проверить ModelState? - PullRequest
47 голосов
/ 13 ноября 2008

Как я могу проверить Controller.ViewData.ModelState? Я бы предпочел сделать это без каких-либо поддельных рамок.

Ответы [ 6 ]

44 голосов
/ 26 февраля 2009

Конечно, вам не обязательно использовать макет, если вы используете шаблон репозитория для своих данных.

Некоторые примеры: http://www.singingeels.com/Articles/Test_Driven_Development_with_ASPNET_MVC.aspx

// Test for required "FirstName".
   controller.ViewData.ModelState.Clear();

   newCustomer = new Customer
   {
       FirstName = "",
       LastName = "Smith",
       Zip = "34275",    
   };

   controller.Create(newCustomer);

   // Make sure that our validation found the error!
   Assert.IsTrue(controller.ViewData.ModelState.Count == 1, 
                 "FirstName must be required.");
35 голосов
/ 07 апреля 2011
//[Required]
//public string Name { get; set; }
//[Required]
//public string Description { get; set; }

ProductModelEdit model = new ProductModelEdit() ;
//Init ModelState
var modelBinder = new ModelBindingContext()
{
    ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(
                      () => model, model.GetType()),
    ValueProvider=new NameValueCollectionValueProvider(
                        new NameValueCollection(), CultureInfo.InvariantCulture)
};
var binder=new DefaultModelBinder().BindModel(
                 new ControllerContext(),modelBinder );
ProductController.ModelState.Clear();
ProductController.ModelState.Merge(modelBinder.ModelState);

ViewResult result = (ViewResult)ProductController.CreateProduct(null,model);
Assert.IsTrue(result.ViewData.ModelState["Name"].Errors.Count > 0);
Assert.True(result.ViewData.ModelState["Description"].Errors.Count > 0);
Assert.True(!result.ViewData.ModelState.IsValid);
11 голосов
/ 10 июля 2016

Для тестирования веб-API используйте метод Validate на контроллере:

var controller = new MyController();
controller.Configuration = new HttpConfiguration();
var model = new MyModel();

controller.Validate(model);
var result = controller.MyMethod(model);
5 голосов
/ 20 марта 2018

столкнулся с этой проблемой для .NetCore 2.1 Вот мое решение:

Метод расширения

using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;

namespace MyExtension
{
    public static void BindViewModel<T>(this Controller controller, T model)
    {
        if (model == null) return;

        var context = new ValidationContext(model, null, null);
        var results = new List<ValidationResult>();

        if (!Validator.TryValidateObject(model, context, results, true))
        {
            controller.ModelState.Clear();
            foreach (ValidationResult result in results)
            {
                var key = result.MemberNames.FirstOrDefault() ?? "";
                controller.ModelState.AddModelError(key, result.ErrorMessage);
            }
        }
    }
}

Просмотр модели

public class MyViewModel
{
    [Required]
    public string Name { get; set; }
}

Модульный тест

public async void MyUnitTest()
{
    // helper method to create instance of the Controller
    var controller = this.CreateController();

    var model = new MyViewModel
    {
        Name = null
    };

    // here we call the extension method to validate the model
    // and set the errors to the Controller's ModelState
    controller.BindViewModel(model);

    var result = await controller.ActionName(model);

    Assert.NotNull(result);
    var viewResult = Assert.IsType<BadRequestObjectResult>(result);
}
0 голосов
/ 02 октября 2018

Это позволит вам не только проверить, существует ли ошибка, но и проверить, что она имеет то же сообщение об ошибке, что и ожидалось. Например, оба эти параметра являются Обязательными, поэтому их сообщение об ошибке отображается как «Обязательный».

Разметка модели:

//[Required]
//public string Name { get; set; }
//[Required]
//public string Description { get; set; }

Код юнит-теста:

ProductModelEdit model = new ProductModelEdit() ;
//Init ModelState
var modelBinder = new ModelBindingContext()
{
    ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(
                      () => model, model.GetType()),
    ValueProvider=new NameValueCollectionValueProvider(
                        new NameValueCollection(), CultureInfo.InvariantCulture)
};
var binder=new DefaultModelBinder().BindModel(
                 new ControllerContext(),modelBinder );
ProductController.ModelState.Clear();
ProductController.ModelState.Merge(modelBinder.ModelState);

ViewResult result = (ViewResult)ProductController.CreateProduct(null,model);
Assert.IsTrue(!result.ViewData.ModelState.IsValid);
//Make sure Name has correct errors
Assert.IsTrue(result.ViewData.ModelState["Name"].Errors.Count > 0);
Assert.AreEqual(result.ViewData.ModelState["Name"].Errors[0].ErrorMessage, "Required");
//Make sure Description has correct errors
Assert.IsTrue(result.ViewData.ModelState["Description"].Errors.Count > 0);
Assert.AreEqual(result.ViewData.ModelState["Description"].Errors[0].ErrorMessage, "Required");
0 голосов
/ 02 июня 2015

В дополнение к отличным ответам, приведенным выше, проверьте это фантастическое использование защищенного метода TryValidateModel в классе Controller.

Просто создайте тестовый класс, унаследованный от контроллера, и передайте модель в метод TryValidateModel. Вот ссылка: http://blog.icanmakethiswork.io/2013/03/unit-testing-modelstate.html

Полное признание за это решение принадлежит Джону Рейли и Марку Талари.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...