Как использовать Moq для проверки того, что PropertyChanged вызывается с ожидаемым именем объекта и свойства? - PullRequest
0 голосов
/ 18 июня 2020

Используя NUnit и Moq, я хотел бы заменить код обработчика PropertyChanged в следующем тесте на Moq, если это сделает тест короче и понятнее. В настоящее время я не понимаю, как это сделать в Moq, проверяя, что PropertyChanged вызывается один раз для IsDirty и один раз для LocalDatabaseFilePath, каждый раз с ожидаемым объектом (o в коде). Кто-нибудь может посоветовать, как это сделать с Moq, пожалуйста?

        [Test]
        [Category("Fast Tests")]
        [Category("PropertyChanged Events")]
        public void FactoryResetCommand_AllPropertiesChangedInViewModel_PropertyChangedEventsFiredAsExpected()
        {
            // Arrange

            string expectedLocalDatabaseFilePath = "eldfp";
            string otherLocalDatabaseFilePath = "other" + expectedLocalDatabaseFilePath;

            Mock<IDataStoreSettingsDataModel> stubDataModel = new Mock<IDataStoreSettingsDataModel>();
            stubDataModel.Setup(x => x.LocalDatabaseFilePath).Returns(expectedLocalDatabaseFilePath);

            IDataStoreSettingsViewModel sutViewModel = new DataStoreSettingsViewModel(
                stubDataModel.Object,
                ReportExceptionAsync);
            sutViewModel.LocalDatabaseFilePath = otherLocalDatabaseFilePath;

            sutViewModel.IsDirty = false;

            // I'd like to replace the following by Moq if shorter/clearer

            int propertyChangedCountIsDirty = 0;
            int propertyChangedCountLocalDatabaseFilePath = 0;
            object? objIsDirty = null;
            object? objLocalDatabaseFilePath = null;

            sutViewModel.PropertyChanged += ((o, e) =>
            {
                switch (e?.PropertyName)
                {
                    case nameof(DataStoreSettingsViewModel.IsDirty):
                        objIsDirty = o;
                        ++propertyChangedCountIsDirty;
                        break;
                    case nameof(DataStoreSettingsViewModel.LocalDatabaseFilePath):
                        objLocalDatabaseFilePath = o;
                        ++propertyChangedCountLocalDatabaseFilePath;
                        break;
                }
            });

            // I'd like to replace the above by Moq if shorter/clearer

            // Act

            if (sutViewModel.FactoryResetCommand.CanExecute(null))
                sutViewModel.FactoryResetCommand.Execute(null);

            // Assert

            Assert.AreEqual(1, propertyChangedCountIsDirty);
            Assert.AreEqual(1, propertyChangedCountLocalDatabaseFilePath);
            Assert.AreSame(sutViewModel, objIsDirty);
            Assert.AreSame(sutViewModel, objLocalDatabaseFilePath);
        }

1 Ответ

0 голосов
/ 18 июня 2020

Сам разобрался.

После добавления следующего интерфейса:

    public interface IPropertyChangedEventHandler
    {
        void PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e);
    }

Тест с использованием Moq выглядит так:

        [Test]
        [Category("Fast Tests")]
        [Category("PropertyChanged Events")]
        public void FactoryResetCommand_AllPropertiesChangedInViewModel_PropertyChangedEventsFiredAsExpected()
        {
            // Arrange

            string originalLocalDatabaseFilePath = "oldfp";
            string otherLocalDatabaseFilePath = "other" + originalLocalDatabaseFilePath;

            Mock<IPropertyChangedEventHandler> mockPropertyChangedEventHandler = new Mock<IPropertyChangedEventHandler>();

            Mock<IDataStoreSettingsDataModel> stubDataModel = new Mock<IDataStoreSettingsDataModel>();
            stubDataModel.Setup(x => x.LocalDatabaseFilePath).Returns(originalLocalDatabaseFilePath);

            IDataStoreSettingsViewModel sutViewModel = new DataStoreSettingsViewModel(
                stubDataModel.Object,
                ReportExceptionAsync);
            sutViewModel.LocalDatabaseFilePath = otherLocalDatabaseFilePath;

            sutViewModel.IsDirty = false;

            sutViewModel.PropertyChanged += mockPropertyChangedEventHandler.Object.PropertyChanged;

            // Act

            if (sutViewModel.FactoryResetCommand.CanExecute(null))
                sutViewModel.FactoryResetCommand.Execute(null);

            // Assert

            mockPropertyChangedEventHandler.Verify(x => x.PropertyChanged(sutViewModel,
                It.Is<System.ComponentModel.PropertyChangedEventArgs>(e => e.PropertyName == nameof(DataStoreSettingsViewModel.IsDirty))), 
                Times.Once);
            mockPropertyChangedEventHandler.Verify(x => x.PropertyChanged(sutViewModel,
                It.Is<System.ComponentModel.PropertyChangedEventArgs>(e => e.PropertyName == nameof(DataStoreSettingsViewModel.LocalDatabaseFilePath))), 
                Times.Once);
        }
...