Главная страница Случайная страница КАТЕГОРИИ: АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника |
Проверка валидации
Если мы просто вызовем что-то типа: var registerUser = new UserView() { Email = " user@sample.com", Password = " 123456", ConfirmPassword = " 1234567", AvatarPath = " /file/no-image.jpg", BirthdateDay = 1, BirthdateMonth = 12, BirthdateYear = 1987, Captcha = " 1234" }; var result = controller.Register(registerUser); То, во-первых, никакая неявная валидация не выполнится, а во-вторых, у нас там есть session и мы ее не проинициализировали, она null и всё – ошибка. Так что проверку валидации (та, что в атрибутах) будем устраивать через отдельный класс. Назовем его Валидатор Валидаторович (/Tools/Validator.cs): public class ValidatorException: Exception { public ValidationAttribute Attribute { get; private set; }
public ValidatorException(ValidationException ex, ValidationAttribute attribute) : base(attribute.GetType().Name, ex) { Attribute = attribute; } }
public class Validator { public static void ValidateObject< T> (T obj) { var type = typeof(T); var meta = type.GetCustomAttributes(false).OfType< MetadataTypeAttribute> ().FirstOrDefault(); if (meta! = null) { type = meta.MetadataClassType; }
var typeAttributes = type.GetCustomAttributes(typeof(ValidationAttribute), true).OfType< ValidationAttribute> (); var validationContext = new ValidationContext(obj); foreach (var attribute in typeAttributes) { try { attribute.Validate(obj, validationContext); } catch (ValidationException ex) { throw new ValidatorException(ex, attribute); } }
var propertyInfo = type.GetProperties(); foreach (var info in propertyInfo) { var attributes = info.GetCustomAttributes(typeof(ValidationAttribute), true).OfType< ValidationAttribute> (); foreach (var attribute in attributes) { var objPropInfo = obj.GetType().GetProperty(info.Name); try { attribute.Validate(objPropInfo.GetValue(obj, null), validationContext); } catch (ValidationException ex) { throw new ValidatorException(ex, attribute); } } } } }
Итак, что тут у нас происходит. Вначале мы получаем все атрибуты класса T, которые относятся к типу ValidationAttribute: var typeAttributes = type.GetCustomAttributes(typeof(ValidationAttribute), true).OfType< ValidationAttribute> (); var validationContext = new ValidationContext(obj); foreach (var attribute in typeAttributes) { try { attribute.Validate(obj, validationContext); } catch (ValidationException ex) { throw new ValidatorException(ex, attribute); } }
Потом аналогично для каждого свойства: var propertyInfo = type.GetProperties(); foreach (var info in propertyInfo) { var attributes = info.GetCustomAttributes(typeof(ValidationAttribute), true).OfType< ValidationAttribute> (); foreach (var attribute in attributes) { var objPropInfo = obj.GetType().GetProperty(info.Name); try { attribute.Validate(objPropInfo.GetValue(obj, null), validationContext); } catch (ValidationException ex) { throw new ValidatorException(ex, attribute); } } } Если валидация не проходит, то происходит исключение, и мы оборачиваем его в ValidatorException, передавая еще и атрибут, по которому произошло исключение. Теперь по поводу капчи и Session. Мы должны контроллеру передать контекст (MockHttpContext): var controller = DependencyResolver.Current.GetService< Areas.Default.Controllers.UserController> (); var httpContext = new MockHttpContext().Object; ControllerContext context = new ControllerContext(new RequestContext(httpContext, new RouteData()), controller); controller.ControllerContext = context; controller.Session.Add(CaptchaImage.CaptchaValueKey, " 1111"); И теперь всё вместе: [Test] public void Index_RegisterUserWithDifferentPassword_ExceptionCompare() { //init var controller = DependencyResolver.Current.GetService< Areas.Default.Controllers.UserController> (); var httpContext = new MockHttpContext().Object; ControllerContext context = new ControllerContext(new RequestContext(httpContext, new RouteData()), controller); controller.ControllerContext = context;
//act var registerUserView = new UserView() { Email = " user@sample.com", Password = " 123456", ConfirmPassword = " 1234567", AvatarPath = " /file/no-image.jpg", BirthdateDay = 1, BirthdateMonth = 12, BirthdateYear = 1987, Captcha = " 1111" }; try { Validator.ValidateObject< UserView> (registerUserView); } catch (Exception ex) { Assert.IsInstanceOf< ValidatorException> (ex); Assert.IsInstanceOf< System.ComponentModel.DataAnnotations.CompareAttribute> (((ValidatorException)ex).Attribute); } } Запускаем, и всё получилось. Но капча проверяется непосредственно в методе контроллера. Специально для капчи: [Test] public void Index_RegisterUserWithWrongCaptcha_ModelStateWithError() { //init var controller = DependencyResolver.Current.GetService< Areas.Default.Controllers.UserController> (); var httpContext = new MockHttpContext().Object; ControllerContext context = new ControllerContext(new RequestContext(httpContext, new RouteData()), controller); controller.ControllerContext = context; controller.Session.Add(CaptchaImage.CaptchaValueKey, " 2222 "); //act var registerUserView = new UserView() { Email = " user@sample.com", Password = " 123456", ConfirmPassword = " 1234567", AvatarPath = " /file/no-image.jpg", BirthdateDay = 1, BirthdateMonth = 12, BirthdateYear = 1987, Captcha = " 1111 " };
var result = controller.Register(registerUserView); Assert.AreEqual(" Текст с картинки введен неверно", controller.ModelState[" Captcha" ].Errors[0].ErrorMessage); } Круто?
|