Проверка ASP.NET DataAnnotations Поблочного тестирования

Я использую DataAnnotations для своей проверки допустимости модели т.е.

    [Required(ErrorMessage="Please enter a name")]
    public string Name { get; set; }

В моем контроллере я проверяю значение ModelState. Это правильно возвращает false для недопустимых данных модели, отправленных от моего представления.

Однако при выполнении модульного теста моего действия контроллера, ModelState всегда возвращает true:

    [TestMethod]
    public void Submitting_Empty_Shipping_Details_Displays_Default_View_With_Error()
    {
        // Arrange
        CartController controller = new CartController(null, null);
        Cart cart = new Cart();
        cart.AddItem(new Product(), 1);

        // Act
        var result = controller.CheckOut(cart, new ShippingDetails() { Name = "" });

        // Assert
        Assert.IsTrue(string.IsNullOrEmpty(result.ViewName));
        Assert.IsFalse(result.ViewData.ModelState.IsValid);
    }

Я должен сделать что-либо дополнительное для установки проверки допустимости модели в моих тестах?

Спасибо,

Ben

65
задан Ben Foster 30 January 2010 в 12:03
поделиться

2 ответа

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

В MVC2 были внесены изменения по сравнению с валидацией на входе, поэтому точное поведение зависит от используемой версии. См. http://bradwilson.typepad.com/blog/2010/01/input-validation-vs-model-validation-in-aspnet-mvc.html для получения более подробной информации относительно MVC и MVC 2.

[EDIT] Я думаю, что самым чистым решением для этого является вызов UpdateModel на контроллере вручную при тестировании, предоставляя пользовательский имитатор ValueProvider. Это должно запустить проверку и правильно установить ModelState.

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

Я просматривал http://bradwilson.typepad.com/blog/2009/04/dataannotations-and-aspnet-mvc.html , в этом посте мне не понравилась идея поместить валидационные тесты в тест контроллера и немного вручную проверять в каждом тесте, существует ли атрибут валидации или нет. Итак, ниже приведен вспомогательный метод и его использование, которое я реализовал, он работает как для EDM (который имеет атрибуты метаданных, потому что мы не можем применять атрибуты к автоматически сгенерированным классам EDM), так и для объектов POCO, которые имеют ValidationAttributes, примененные к их свойствам. .

Вспомогательный метод не анализирует иерархические объекты, но проверка может быть проверена на плоских отдельных объектах (на уровне типа)

class TestsHelper
{

    internal 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 propertyInfo = type.GetProperties();
        foreach (var info in propertyInfo)
        {
            var attributes = info.GetCustomAttributes(false).OfType<ValidationAttribute>();
            foreach (var attribute in attributes)
            {
                var objPropInfo = obj.GetType().GetProperty(info.Name);
                attribute.Validate(objPropInfo.GetValue(obj, null), info.Name);
            }
        }
    }
}

 /// <summary>
/// Link EDM class with meta data class
/// </summary>
[MetadataType(typeof(ServiceMetadata))]
public partial class Service
{
}

/// <summary>
/// Meta data class to hold validation attributes for each property
/// </summary>
public class ServiceMetadata
{
    /// <summary>
    /// Name 
    /// </summary>
    [Required]
    [StringLength(1000)]
    public object Name { get; set; }

    /// <summary>
    /// Description
    /// </summary>
    [Required]
    [StringLength(2000)]
    public object Description { get; set; }
}


[TestFixture]
public class ServiceModelTests 
{
    [Test]
    [ExpectedException(typeof(ValidationException), ExpectedMessage = "The Name field is required.")]
    public void Name_Not_Present()
    {
        var serv = new Service{Name ="", Description="Test"};
        TestsHelper.ValidateObject(serv);
    }

    [Test]
    [ExpectedException(typeof(ValidationException), ExpectedMessage = "The Description field is required.")]
    public void Description_Not_Present()
    {
        var serv = new Service { Name = "Test", Description = string.Empty};
        TestsHelper.ValidateObject(serv);
    }

}

это еще один пост http://johan.driessen.se/archive/2009 /11/18/testing-dataannotation-based-validation-in-asp.net-mvc.aspx, в котором говорится о проверке в .Net 4, но я думаю, что буду придерживаться своего вспомогательного метода, который действителен в и 3,5, и 4

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

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