Модульный тест INotifyPropertyChanged с использованием Rhino Mocks - PullRequest
0 голосов
/ 23 января 2020

У меня есть класс, который реализует INotifyPropertyChanged, и мне нужно проверить, правильно ли реализован этот интерфейс. Я хочу сделать это, используя объект Rhino Mock.

class MyClass : INotifyPropertyChanged
{
    public int X
    {
        get => ...;
        set => ... // should check if value changes and raise event PropertyChanged
    }
}

Я хочу проверить, что при изменении значения X это событие PropertyChanged вызывается ровно один раз с соответствующими параметрами.

MyClass testObject = new MyClass();

// the mock:
PropertyChangedEventHandler a = MockRepository.GenerateMock<PropertyChangedEventHandler>();
testObject.PropertyChanged += a;

// expect that the mock will be called exactly once, with the proper parameters
a.Expect( (x) => ???)
 .Repeat()
 .Once();

// change X, and verify that the event handler has been called exactly once
testObject.X = testObject.X + 1;

a.VerifyAllExpectations(); ???

Я думаю, что я на правильном пути, но я не могу заставить его работать.

1 Ответ

0 голосов
/ 03 февраля 2020

Иногда на самом деле нет необходимости использовать макет, если нет эффектов, которые могут повлиять на использование реальной вещи.

В следующем простом примере создается экземпляр делегата и проверяется ожидаемое поведение

Что я хочу проверить, так это то, что когда X изменяет значение, это событие PropertyChanged вызывается ровно один раз с соответствующими параметрами.

[TestClass]
public class MyClassTests {
    [TestMethod]
    public void Should_Call_PropertyChanged_Once() {
        //Arrange            
        //Store calls
        IDictionary<string, int> properties = new Dictionary<string, int>();
        PropertyChangedEventHandler handler = new PropertyChangedEventHandler((s, e) => {
            if (!properties.ContainsKey(e.PropertyName))
                properties.Add(e.PropertyName, 0);

            properties[e.PropertyName]++;
        });

        MyClass testObject = new MyClass();
        testObject.PropertyChanged += handler;

        string expectedPropertyName = nameof(MyClass.X);
        int expectedCount = 1;

        //Act
        testObject.X = testObject.X + 1;

        //Assert - using FluentAssertions
        properties.Should().ContainKey(expectedPropertyName);
        properties[expectedPropertyName].Should().Be(expectedCount);
    }

    class MyClass : INotifyPropertyChanged {
        public event PropertyChangedEventHandler PropertyChanged = delegate { };

        void raisePropertyChanged([CallerMemberName]string propertyName = null) {
            PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        int x;
        public int X {
            get => x;
            set {
                if (value != x) {
                    x = value;
                    raisePropertyChanged();
                }
            }
        }
    }
}
...