Unit testing that events are raised in C# (in order)

前端 未结 7 2321
小蘑菇
小蘑菇 2020-11-29 16:02

I have some code that raises PropertyChanged events and I would like to be able to unit test that the events are being raised correctly.

The code that i

7条回答
  •  余生分开走
    2020-11-29 16:39

    Don't write a test for each member - this is much work

    (maybe this solution is not perfect for every situation - but it shows a possible way. You might need to adapt it for your use case)

    It's possible to use reflection in a library to test if your members are all responding to your property changed event correctly:

    • PropertyChanged event is raised on setter access
    • Event is raised correct (name of property equals argument of raised event)

    The following code can be used as a library and shows how to test the following generic class

    using System.ComponentModel;
    using System.Linq;
    
    /// 
    /// Check if every property respons to INotifyPropertyChanged with the correct property name
    /// 
    public static class NotificationTester
        {
            public static object GetPropertyValue(object src, string propName)
            {
                return src.GetType().GetProperty(propName).GetValue(src, null);
            }
    
            public static bool Verify(T inputClass) where T : INotifyPropertyChanged
            {
                var properties = inputClass.GetType().GetProperties().Where(x => x.CanWrite);
                var index = 0;
    
                var matchedName = 0;
                inputClass.PropertyChanged += (o, e) =>
                {
                    if (properties.ElementAt(index).Name == e.PropertyName)
                    {
                        matchedName++;
                    }
    
                    index++;
                };
    
                foreach (var item in properties)
                { 
                    // use setter of property
                    item.SetValue(inputClass, GetPropertyValue(inputClass, item.Name));
                }
    
                return matchedName == properties.Count();
            }
        }
    

    The tests of your class can now be written as. (maybe you want to split the test into "event is there" and "event raised with correct name" - you can do this yourself)

    [TestMethod]
    public void EveryWriteablePropertyImplementsINotifyPropertyChangedCorrect()
    {
        var viewModel = new TestMyClassWithINotifyPropertyChangedInterface();
        Assert.AreEqual(true, NotificationTester.Verify(viewModel));
    }
    

    Class

    using System.ComponentModel;
    
    public class TestMyClassWithINotifyPropertyChangedInterface : INotifyPropertyChanged
    {
            public event PropertyChangedEventHandler PropertyChanged;
    
            protected void NotifyPropertyChanged(string name)
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(name));
                }
            }
    
            private int id;
    
            public int Id
            {
                get { return id; }
                set { id = value;
                    NotifyPropertyChanged("Id");
                }
            }
    }
    

提交回复
热议问题