Подтвердить что ты не робот

ASP post MVC Controller post метод unit test: ModelState.IsValid всегда true

Я написал свои первые модульные тесты для веб-приложения ASP.NET MVC. Все работает отлично, и это дает мне ценную информацию, но я не могу проверить ошибки в модели представления. ModelState.IsValid всегда верен, даже если некоторые значения не заполнены (пустая строка или нуль).

Я уже прочитал, что проверка модели происходит, когда размещенные данные сопоставляются с моделью, и вам нужно написать код для самостоятельной проверки модели:

Я попробовал три примера, приведенные на связанных страницах, но, похоже, это не работает для меня.

Некоторые коды:

Моя модель просмотра

...
[Required(ErrorMessageResourceName = "ErrorFirstName", ErrorMessageResourceType = typeof(Mui))]
[MaxLength(50)]
[Display(Name = "Firstname", ResourceType = typeof(Mui))]
public string FirstName { get; set; }
...

Контроллер

...
 [HttpPost]
    public ActionResult Index(POSViewModel model)
    {
        Contract contract = contractService.GetContract(model.ContractGuid.Value);

        if (!contract.IsDirectDebit.ToSafe())
        {
            ModelState.Remove("BankName");
            ModelState.Remove("BankAddress");
            ModelState.Remove("BankZip");
            ModelState.Remove("BankCity");
            ModelState.Remove("AccountNr");
        }

        if (ModelState.IsValid)
        {
            ...

            contractValidationService.Create(contractValidation);
            unitOfWork.SaveChanges();

            return RedirectToAction("index","thanks");
        }
        else
        {
            return Index(model.ContractGuid.ToString());
        }
    }

Мой unit test

  posViewModel.FirstName = null;
  posViewModel.LastName = "";
 ...
 var modelBinder = new ModelBindingContext()
        {
            ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => posViewModel, posViewModel.GetType()),
            ValueProvider = new NameValueCollectionValueProvider(new System.Collections.Specialized.NameValueCollection(), CultureInfo.InvariantCulture)
        };
        var binder = new DefaultModelBinder().BindModel(new ControllerContext(), modelBinder);
        posController.ModelState.Clear();
        posController.ModelState.Merge(modelBinder.ModelState);

        ActionResult result = posController.Index(posViewModel);

        //Assert
        mockContractValidationService.Verify(m => m.Create(It.IsAny<ContractValidation>()), Times.Never);
        Assert.IsInstanceOfType(result, typeof(ViewResult));

В представлении я использую ненавязчивую проверку JavaScript, и он работает.

4b9b3361

Ответ 1

Я нашел это решение: SO: проверка не работает, когда я использую Validator.TryValidateObject в сочетании с решением @Kenneth при условии:

[TestMethod]
    public void test_validation()
    {
        var sut = new POSViewModel();
        // Set some properties here
        var context = new ValidationContext(sut, null, null);
        var results = new List<ValidationResult>();
        TypeDescriptor.AddProviderTransparent(new AssociatedMetadataTypeTypeDescriptionProvider(typeof(POSViewModel), typeof(POSViewModel)), typeof(POSViewModel));

        var isModelStateValid = Validator.TryValidateObject(sut, context, results, true);

        // Assert here
    }

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

Ответ 2

Вы пытаетесь одновременно протестировать две разные вещи. Контроллер не отвечает за проверку состояния модели, только для того, чтобы вести себя по-другому в зависимости от результата этой проверки. Поэтому ваши юнит-тесты для контроллера не должны пытаться проверить проверку, что должно быть сделано в другом тесте. По-моему, у вас должно быть три модульных теста:

  • Проверяет правильность проверки модели
  • Тот, который проверяет правильность поведения контроллера при корректном действии modelstate
  • Тот, который проверяет правильность поведения контроллера при несогласии modelstate

Вот как вы можете это сделать:

1. Проверка модели

[Test]
public void test_validation()
{
    var sut = new POSViewModel();
    // Set some properties here
    var context = new ValidationContext(sut, null, null);
    var results = new List<ValidationResult>();
    var isModelStateValid =Validator.TryValidateObject(sut, context, results, true);

    // Assert here
}

2.Контроллер с недопустимым файлом модели

[Test]
public void test_controller_with_model_error()
{
    var controller = new PosController();
    controller.ModelState.AddModelError("test", "test");

    ActionResult result = posController.Index(new PosViewModel());

    // Assert that the controller executed the right actions when the model is invalid
}

3.Controller с действительным modelstate

[Test]
public void test_controller_with_valid_model()
{
    var controller = new PosController();
    controller.ModelState.Clear();

    ActionResult result = posController.Index(new PosViewModel());

    // Assert that the controller executed the right actions when the model is valid
}