Тестирование пользовательской проверки свойства, зависящего от другого свойства, возвращает ArgumentNullException

Я пытаюсь написать тест XUnit для проверки моего собственного валидатора. Валидатор проверяет значение другого свойства, которое указывает, должно ли проверенное свойство быть нулевым или иметь значение. Однако тест возвращает ArgumentNullException, когда я использую метод TryValidateProperty.

Валидатор:

public class ConcatenatedDataValidator : ValidationAttribute
{
    public string PropertyName { get; private set; }
    public ConcatenatedDataValidator(string propertyName)
    {
        this.PropertyName = propertyName;
    }


    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var property = validationContext.ObjectType.GetProperty(PropertyName);
        if(property == null && value != null)
        {
            return new ValidationResult(string.Format("{0} is null", PropertyName));
        }
        var chosenValue = property.GetValue(validationContext.ObjectInstance, null);

        if(chosenValue.Equals("00") && (value == null || value.Equals(string.Empty))
            ||  chosenValue.Equals("01") && value != null) 
        {
            return new ValidationResult(this.FormatErrorMessage(validationContext.DisplayName));
        }

        return null;
    }  
}

Тест:

public class ConcatenatedDataValidatorTests
{
    private TestedModel model;
    private ValidationContext context;
    private List<ValidationResult> results;

    [Fact]
    public void IsValid_OtherValueIs00ThisValueIsNull_ReturnFalse()
    {
        // arrange
        var concatenatedDataValidator = new ConcatenatedDataValidator("OtherProperty");
        model = new TestedModel();
        model.OtherProperty = "00";
        model.ThisProperty = null;
        context = new ValidationContext(model);
        results = new List<ValidationResult>();

        // act
        var result = Validator.TryValidateProperty(model.ThisProperty, context, results);

        // assert
        Assert.False(result);

    }
}

Тест возвращается

System.ArgumentNullException : Value cannot be null. Parameter name: propertyName

в актовой части. Я хотел бы протестировать только это одно свойство, так как в модели у меня есть множество других свойств с атрибутом Required, и я хочу, чтобы тесты были как можно более простыми и тестировались только мой собственный валидатор. Есть ли способ решить эту проблему?


person Lordzio    schedule 09.08.2019    source источник


Ответы (1)


Это ожидаемое поведение. Поскольку Validator.TryValidateProperty< /a> указывает, что если value равно null, выбрасывается System.ArgumentNullException.

Если вы хотите проверить это поведение/случай, когда значение вашего свойства равно null, вам следует поймать исключение и проверить его, хотя в основном это тестирование .NET framework.

Это также указывает на то, что вы можете отключить проверку value == null в методе IsValid, так как она никогда не сработает.

ОБНОВЛЕНИЕ

Вся ошибка относится к закрытому методу EnsureValidPropertyType, вызываемому внутри TryValidateProperty (см. ="nofollow noreferrer">здесь).

Это вызвано тем, что ValidationContext.MemberName.

Чтобы решить эту проблему, вы должны установить MemberName во время создания вашего ValidationContext (если .NET 4.7.2 и ранее)

ValidationContext context = new ValidationContext(model)
{
        MemberName = "ThisProperty"
};

или измените поведение по умолчанию в конфигурации вашего приложения (.NET 4.8).

<configuration>
   <appSettings>
      <add key="aspnet:GetValidationMemberName" value="true" />
   </appSettings>
</configuration>
person FeRaaC    schedule 09.08.2019
comment
Как насчет тестового случая, когда я ожидаю, что значение не будет нулевым. Когда я набираю model.ThisProperty = "asd"; в своем тесте, он все равно выдает то же исключение. И он по-прежнему говорит об аргументе propertyName, переданном в конструкторе. - person Lordzio; 09.08.2019
comment
Также метод ValidationAttribute.IsValid не возвращает System.ArgumentNullException и не указывает, что переданное значение не может быть нулевым. Может возникнуть ситуация, когда я просто ничего не передаю этому свойству, даже если я указал в другом, что хочу передать это здесь. В основном я пытаюсь сделать валидатор, который делает свойство обязательным в зависимости от значения другого свойства. - person Lordzio; 09.08.2019
comment
О, да, это относится к частному методу EnsureValidPropertyType, вызываемому внутри TryValidateProperty (см. rel="nofollow noreferrer">здесь). Это вызвано тем, что ValidationContext.MemberName. Я обновляю свой ответ решением этой проблемы. - person FeRaaC; 09.08.2019
comment
Да, решение из обновления работает отлично. Большое спасибо :) РЕДАКТИРОВАТЬ: протестировано на .NET 4.6.1 - person Lordzio; 09.08.2019
comment
@Lordzio, это здорово. Просто чтобы убедиться, что model.ThisProperty = null по-прежнему должно вызывать исключение. - person FeRaaC; 09.08.2019