Как проверить ошибки модульного тестирования в бизнес-объекте IDataErrorInfo?

Я пишу (пытаюсь писать) модульные тесты для приложения WPF.

Бизнес-объекты, которые пользовательский интерфейс связывает для реализации IDataErrorInfo, так что, когда я устанавливаю ValidatesOnDataErrors=True в своем XML-представлении, индексатор ошибок (this[]) вызывается каждый раз, когда вызывается установщик для связанного бизнес-объекта. Эта часть великолепна.

Теперь, если я вызываю установщик того же свойства из unitTest, он никогда не вызывает индексатор ошибок. Как заставить индексатор IDataErrorInfo оцениваться из модульного теста?

просто для иллюстрации вот один из моих простых индексаторов ошибок, который содержит свойство Name. Установка «myObject.Name = string.Empty;» вызывает установщик, но не индексатор ошибок, когда я делаю это в своих модульных тестах.

        public string Name
    {
        get { return _name; }
        set
        {
            _name = value;
            IsDirty = true;
            OnPropertyChanged("Name");
        }
    }

        #region IDataErrorInfo

    public Dictionary<string, string> ErrorCollection;

    public string this[string property]
    {
        get
        {
            string msg = null;
            switch (property)
            {
                case "Name":
                    if (string.IsNullOrEmpty(Name))
                        msg = "ICU Name is required.";
                    else if (Name.Length < 4)
                        msg = "ICU Name must contain at least 4 characters.";
                    else if (_parent.Units.AsEnumerable().Count(u => u.Name == Name) > 1)
                        msg = Name + " already exists, please change to a different Name.";
                    break;
            }


            if (msg != null && !ErrorCollection.ContainsKey(property))
                ErrorCollection.Add(property, msg);
            if (msg == null && ErrorCollection.ContainsKey(property))
                ErrorCollection.Remove(property);

            return msg;
        }
    }

    public string Error
    {
        get { return null; }
    }
    #endregion

Спасибо!


person Bob    schedule 26.02.2010    source источник


Ответы (3)


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

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

person Timores    schedule 26.02.2010
comment
Да, и ваш подход, и подход Джоэла Б. Фанта отлично работают. Меньше насмешек, просто вызывая индексатор, а не перехватывая событие PropertyChanged. Спасибо всем. - person Bob; 26.02.2010

Вам нужно самостоятельно подключиться к событию PropertyChanged, а затем при вызове вашего обработчика вызвать индексатор с именем свойства. Или не подключайтесь к событию и не вызывайте индексатор с именем свойства, которое вы тестируете.

Это то, что делает .NET. Он вызывает индексатор с именами свойств.

MyClass mc = new MyClass();
mc.Name = "abc";
string error = mc["Name"];
person Joel B Fant    schedule 26.02.2010

Следующие тесты NUnit вызывают индексатор для свойства Name и проверяют сообщение об ошибке.

[TestFixture]
public class MyClassTests
{
    [TestCase("", "ICU Name is required.")]
    [TestCase("A Valid Name", null)]
    public void ValidationIcuNameIsRequired(string name, string expectedResult)
    {
        // Arrange 
        var systemUnderTest = new MyClass();

        // Act
        systemUnderTest.Name = name;

        // Assert
        Assert.AreEqual(expectedResult, systemUnderTest[nameof(systemUnderTest.Name)]);
    }

    [TestCase("a", "ICU Name must contain at least 4 characters.")]
    [TestCase("ab", "ICU Name must contain at least 4 characters.")]
    [TestCase("abc", "ICU Name must contain at least 4 characters.")]
    [TestCase("abcd", null)]
    [TestCase("abcde", null)]
    public void ValidationIcuNameLongerThanThreeCharacters(string name, string expectedResult)
    {
        // Arrange 
        var systemUnderTest = new MyClass();

        // Act
        systemUnderTest.Name = name;

        // Assert
        Assert.AreEqual(expectedResult, systemUnderTest[nameof(systemUnderTest.Name)]);
    }

    [Test]
    public void ValidationParentDoesNotExist()
    {
        // Arrange
        var systemUnderTest = new MyClass();
        string icuName = "TestName";            
        systemUnderTest.Parent.Units.Add(new Unit() {Name = icuName });

        // Act
        systemUnderTest.Name = icuName;

        // Assert
        Assert.AreEqual(icuName + " already exists, please change to a different Name.", systemUnderTest[nameof(systemUnderTest.Name)]);
    }
}
person Andrew Seaford    schedule 19.01.2017