Модульные тесты на проверке MVC

На основе KISS, высокосвязная и слабая связь , задает эти вопросы -

  • , Кто должен знать? мой класс, моя библиотека, другие классы, другие библиотеки, третьи стороны
  • , Что уровень абстракции я должен обеспечить? Делает потребителя, понимают битовые операции.
  • Будет я иметь, должны взаимодействовать через интерфейс от VB/C# и т.д.?

существует замечательная книга" Крупномасштабная Разработка программного обеспечения C++ ", это способствует базовым типам внешне, если можно избежать другого заголовочного файла / интерфейсная зависимость, необходимо попытаться.

75
задан Marc Climent 28 September 2009 в 11:02
поделиться

4 ответа

Вместо передачи BlogPost вы также можете объявить параметр действий как FormCollection . Затем вы можете создать BlogPost самостоятельно и вызвать UpdateModel (model, formCollection.ToValueProvider ()); .

Это запустит проверку для любого поля в FormCollection .

    [HttpPost]
    public ActionResult Index(FormCollection form)
    {
        var b = new BlogPost();
        TryUpdateModel(model, form.ToValueProvider());

        if (ModelState.IsValid)
        {
            _blogService.Insert(b);
            return (View("Success", b));
        }
        return View(b);
    }

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

Я обнаружил, что выполнение этого способа за счет нескольких дополнительных строк кода делает мои модульные тесты более похожими на способ вызова кода во время выполнения, что делает их более ценными. Также вы можете проверить, что происходит, когда кто-то вводит «abc» в элемент управления, привязанный к свойству int.

-3
ответ дан 24 November 2019 в 11:24
поделиться

Когда вы вызываете метод homeController.Index в своем тесте, вы не используете какую-либо среду MVC, которая запускает проверку, поэтому ModelState.IsValid всегда будет истинным. В нашем коде мы вызываем вспомогательный метод Validate непосредственно в контроллере вместо использования внешней проверки. У меня не было большого опыта работы с DataAnnotations (мы используем NHibernate.Validators), возможно, кто-то еще может предложить руководство, как вызвать Validate из вашего контроллера.

7
ответ дан 24 November 2019 в 11:24
поделиться

Я использую ModelBinders в своих тестовых примерах, чтобы иметь возможность обновить значение model.IsValid.

var form = new FormCollection();
form.Add("Name", "0123456789012345678901234567890123456789");

var model = MvcModelBinder.BindModel<AddItemModel>(controller, form);

ViewResult result = (ViewResult)controller.Add(model);

С моим методом MvcModelBinder.BindModel следующим образом (в основном тот же код, который используется внутри инфраструктуры MVC):

        public static TModel BindModel<TModel>(Controller controller, IValueProvider valueProvider) where TModel : class
        {
            IModelBinder binder = ModelBinders.Binders.GetBinder(typeof(TModel));
            ModelBindingContext bindingContext = new ModelBindingContext()
            {
                FallbackToEmptyPrefix = true,
                ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, typeof(TModel)),
                ModelName = "NotUsedButNotNull",
                ModelState = controller.ModelState,
                PropertyFilter = (name => { return true; }),
                ValueProvider = valueProvider
            };

            return (TModel)binder.BindModel(controller.ControllerContext, bindingContext);
        }
2
ответ дан 24 November 2019 в 11:24
поделиться

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

Я нашел этот учебник , в котором объясняется, как вручную проверить ViewModel, использующий DataAnnotations. Фрагмент кода ключа будет ближе к концу сообщения.

Я немного изменил код - в учебнике 4-й параметр TryValidateObject опущен (validateAllProperties). Чтобы получить все аннотации для проверки, необходимо установить значение true.

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

    public static void ValidateViewModel<TViewModel, TController>(this TController controller, TViewModel viewModelToValidate) 
        where TController : ApiController
    {
        var validationContext = new ValidationContext(viewModelToValidate, null, null);
        var validationResults = new List<ValidationResult>();
        Validator.TryValidateObject(viewModelToValidate, validationContext, validationResults, true);
        foreach (var validationResult in validationResults)
        {
            controller.ModelState.AddModelError(validationResult.MemberNames.FirstOrDefault() ?? string.Empty, validationResult.ErrorMessage);
        }
    }

До сих пор это работало для нас очень хорошо.

87
ответ дан 24 November 2019 в 11:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: