Тестирование ModelState всегда действует в asp.net mvc - PullRequest
23 голосов
/ 17 ноября 2011

При тестировании действий моего контроллера ModelState всегда действителен.

public class Product
{
    public int Id { get; set; }

    [Required]
    [StringLength(10)]
    public string Name { get; set; }

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

    [Required]
    public decimal Price { get; set; }
}

И мой контроллер.

public class ProductController : Controller
{
      [HttpPost]
      public ActionResult Create(Product product)
      {
            if (ModelState.IsValid)
            {
                   // Do some creating logic...
                   return RedirectToAction("Display");
            }

             return View(product);              
      }
 }

И тест:

[Test]
public TestInvalidProduct()
{
     var product = new Product();
     var controller = new ProductController();
     controller.Create(product);
     //controller.ModelState.IsValid == true
}

ПочемуmodelState действителен, если у продукта нет названия, описания и цены?

Ответы [ 7 ]

18 голосов
/ 17 ноября 2011

Проверка происходит, когда публикуемые данные привязаны к модели представления.Модель представления затем передается в контроллер.Вы пропускаете часть 1 и передаете модель вида прямо в контроллер.

Вы можете вручную проверить модель вида, используя

System.ComponentModel.DataAnnotations.Validator.TryValidateObject()
10 голосов
/ 05 ноября 2014

Я сталкивался с той же проблемой , и хотя принятый здесь ответ решил проблему «без проверки», это оставило меня с большим отрицательным аспектом: это вызвало бы исключение, когдабыли ошибки проверки вместо простой установки ModelState.Invalid на false.

Я проверял это только в Web Api 2, поэтому я не знаю, в каких проектах это будет доступно, но есть метод ApiController.Validate(object), который вызывает проверку на переданном объекте и устанавливает только ModelState.IsValid в false.Кроме того, вам также нужно создать экземпляр свойства Configuration.

Добавление этого кода в мой модульный тест позволило ему работать:

userController.Configuration = new HttpConfiguration();
userController.Validate(addressInfo);
4 голосов
/ 14 декабря 2012

На другой ноте. Вы должны на самом деле проверить, что возвращает контроллер, и что возвращенный ActionResult - это то, что вы ожидаете. Тестирование ModelBinder должно быть сделано отдельно.

Допустим, вы хотите переключиться на привязку пользовательской модели. Вы можете повторно использовать тесты ModelBinder для нового ModelBinder, который вы создаете. Если ваши бизнес-правила остаются прежними, вы сможете напрямую использовать одни и те же тесты. Однако, если вы смешаете тесты Controller и ModelBinder, и тест не пройден, вы не знаете, в чем проблема - в Controller или ModelBinder.

Допустим, вы тестировали привязку вашей модели примерно так:

[Test]
public void Date_Can_Be_Pulled_Via_Provided_Month_Day_Year()
{
    // Arrange
    var formCollection = new NameValueCollection { 
        { "foo.month", "2" },
        { "foo.day", "12" },
        { "foo.year", "1964" }
    };

    var valueProvider = new NameValueCollectionValueProvider(formCollection, null);
    var modelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, typeof(FwpUser));

    var bindingContext = new ModelBindingContext
    {
        ModelName = "foo",
        ValueProvider = valueProvider,
        ModelMetadata = modelMetadata
    };

    DateAndTimeModelBinder b = new DateAndTimeModelBinder { Month = "month", Day = "day", Year = "year" };
    ControllerContext controllerContext = new ControllerContext();

    // Act
    DateTime result = (DateTime)b.BindModel(controllerContext, bindingContext);

    // Assert
    Assert.AreEqual(DateTime.Parse("1964-02-12 12:00:00 am"), result);
}

Теперь, когда вы ЗНАЕТЕ, что ваша модель привязана правильно, вы можете продолжить тестирование Модели с вашим контроллером в отдельном тесте, чтобы проверить, вернет ли он вам правильный результат. Кроме того, вы можете использовать значения связанной модели для проверки ваших атрибутов валидации.

Таким образом, вы можете получить полный набор тестов, которые покажут, если ваше приложение взорвется, на каком уровне оно это делает. Привязка модели, контроллер или проверка.

3 голосов
/ 24 мая 2015
  1. Создать экземпляр вашего класса контроллера.
  2. Добавление состояния модели и вызов После добавления состояния модели
  3. modelState всегда дает false

    controller.ModelState.AddModelError("key", "error message");
    
    var invalidStateResult = _controller.Index();
    
    Assert.IsNotNull(invalidStateResult);
    
2 голосов
/ 23 ноября 2011

Используйте controller.UpdateModel или controller.TryUpdateModel, чтобы использовать текущий контроллер ValueProvider контроллера для привязки некоторых данных и инициировать проверку привязки модели перед проверкой, если ModelState.IsValid

0 голосов
/ 28 августа 2012

Если вы хотите проверить поведение вашего действия проверки, вы можете просто добавить ModelStateError:

ModelState.AddModelError("Password", "The Password field is required");
0 голосов
/ 17 ноября 2011

Попробуйте контроллер. ViewModel .ModelState.IsValid вместо controller.ModelState.IsValid.

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