Как выполнить модульный тестовый вызов метода в тестируемом (просмотреть модель) классе? - PullRequest
2 голосов
/ 06 июля 2019

Я использую xUnit и Moq .

В моем классе MainViewModel у меня есть метод, который вызывается двумя командами. Метод обновляет несколько свойств: `

public void CommandCompletedControlsSetup()
{
    //TokenSource.Dispose();
    UpdateStatusBar = 0;
    VisibilityStatusBar = Visibility.Hidden;
    ValidateButtons();
    ProgressDisplay = "";
    WorkStatus = "";
    VisibilityCancellingMsg = Visibility.Visible;
    VisibilityCancelTestingBtn = Visibility.Collapsed;
    VisibilityTestingBtn = Visibility.Visible;
    VisibilityCancelUpdatingBtn = Visibility.Collapsed;
    VisibilityUpdatingBtn = Visibility.Visible;
}

И я просто хотел избежать тестирования обновления всего метода для каждой команды. Выполнение первой команды:

public void OnUpdateCancellationExecute(object obj)
{
    _updateDataService.CancelUpdates();

    CommandCompletedControlsSetup(); // here is method call
}

Выполнение второй команды:

public void OnSimulateCancellationExecute(object obj)
{
    _simulateDataService.CancelSimulation();

    CommandCompletedControlsSetup(); // here is method call
}

Так что вместо того, чтобы сделать это дважды:

[Fact]
public void OnSimulateCancellationExecute_UpdatesViewProps_True()
{
    _viewModel.UpdateStatusBar = 1000;
    _viewModel.VisibilityStatusBar = Visibility.Visible;
    _viewModel.ProgressDisplay = "1000/1000";
    _viewModel.WorkStatus = "some status";
    _viewModel.VisibilityCancellingMsg = Visibility.Hidden;
    _viewModel.VisibilityCancelTestingBtn = Visibility.Visible;
    _viewModel.VisibilityTestingBtn = Visibility.Hidden;
    _viewModel.VisibilityCancelUpdatingBtn = Visibility.Visible;
    _viewModel.VisibilityUpdatingBtn = Visibility.Hidden;

    _viewModel.SimulateCancellationCommand.Execute(null);

    Assert.Equal(0, _viewModel.UpdateStatusBar);
    Assert.Equal(Visibility.Hidden, _viewModel.VisibilityStatusBar);
    Assert.Equal("", _viewModel.ProgressDisplay);
    Assert.Equal("", _viewModel.WorkStatus);
    Assert.Equal(Visibility.Visible, _viewModel.VisibilityCancellingMsg);
    Assert.Equal(Visibility.Collapsed, _viewModel.VisibilityCancelTestingBtn);
    Assert.Equal(Visibility.Visible, _viewModel.VisibilityTestingBtn);
    Assert.Equal(Visibility.Collapsed, _viewModel.VisibilityCancelUpdatingBtn);
    Assert.Equal(Visibility.Visible, _viewModel.VisibilityUpdatingBtn);
}

Я хотел сделать что-то вроде этого:

[Fact]
        public void CancellationExecuteMethods_UpdatesViewProps_True()
        {
            _viewModel.SimulateCancellationCommand.Execute(null);

            _viewModel.UpdateCancellationCommand.Execute(null);

            //MainViewModel does not contain definition for Verify - exception
            _viewModel.Verify(sd => sd.CancelUpdates(), Times.Exactly(2));
        }

НО MainViewModel не является издевательским, и я не уверен, что могу его смоделировать? Если да, то как? Если нет, есть ли альтернатива для проверки того, что метод VM был вызван? Или я должен просто оставить это как нечто очевидное и просто протестировать метод сам по себе?

1 Ответ

1 голос
/ 06 июля 2019

Принцип пересмешивания и инверсии зависимости идет рука об руку.Если вы хотите что-то смоделировать, вам нужно «инвертировать зависимость» цели-пересмешника, чтобы вы могли заменить конкретную реализацию фактическим экземпляром смоделированного объекта.В вашем конкретном примере вам нужно будет извлечь CommandCompletedControlsSetup() в отдельный класс и передать его в модель представления с помощью инжектора конструктора.Поскольку модели представления требуется конструктор без параметров, чтобы создать его экземпляр в XAML, это приведет к значительным изменениям при запуске приложения.Я не знаю, как вы делаете это прямо сейчас, но вам нужно будет загрузить приложение, и ваш контейнер DI создаст экземпляры представления и покажет их вручную.

Другой вариант - оставить эти команды в покое и не проверять их явно.Ваши команды состоят из набора методов.Один метод, чтобы быть точным (другой метод - CommandCompletedControlsSetup(), и это вы не хотите тестировать).
В обоих ваших примерах ваши команды вызывают открытый метод класса обслуживания:
updateDataService.CancelUpdates(); и_simulateDataService.CancelSimulation();.
Итак, вы, вероятно, уже тестировали эти сервисы.Если нет, то вы можете или должны их проверить.Если вы тестировали эти сервисы, вы также неявно тестировали команды модели представления, поскольку они зависят от этих сервисов.Таким образом, вы обошли CommandCompletedControlsSetup().

Но в общем, каждое поведение, которое вы хотели бы смоделировать и которое является частью типа, который вы хотите проверить, должно быть внедрено в этот тип.

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

...