views:

116

answers:

2

I am writing (attempting to write) unit tests for a WPF application.

The business objects that the UI binds to implement IDataErrorInfo, such that when I set ValidatesOnDataErrors=True in my View xaml, the error indexer (this[]) is called anytime the setter for the bound business object is called. That part is great.

Now if I call that same property's setter from a unitTest, it never calls the error indexer. How do I force the IDataErrorInfo indexer to be evaluated from within a unit test?

just for illustration, here is one of my simple error indexers that contains a Name property. Setting 'myObject.Name = string.Empty;' does call the setter, but not the error indexer when I do this in my unit tests.

        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

Thanks!

+1  A: 

You need to hook into the PropertyChanged event yourself and then when your handler is called, call the indexer with the property name. Or don't hook into the event and call the indexer with the name of the property you're testing.

That's what .NET does. It calls the indexer with property names.

MyClass mc = new MyClass();
mc.Name = "abc";
string error = mc["Name"];
Joel B Fant
+3  A: 

What I would do in a unit test is to set the value of Name, then explicitly call the indexer to check for the error.

You could hook the PropertyChanged event in the unit test, but I don't think it makes sense, as you'd then have to somehow notify the test method that the event was received and then you'd have to call the indexer anyway.

Timores
Yeah, both yours and Joel B Fant's approach work great. Less mocking by just calling the indexer rather than hooking the PropertyChanged event. Thanks all.
Bob