Насколько moq mock объекты похожи на реальные классы? - PullRequest
0 голосов
/ 03 декабря 2018

Я новичок в юнит-тестах и ​​издевательствах.Поэтому, пожалуйста, не поджаривайте меня:)

Я написал свой первый очень простой модульный тест, и, похоже, он работает.Но я не понимаю, что происходит.Я пытаюсь проверить, что метод showDialog вызывается с аргументом типа EditViewModel, когда вызывается метод OpenEditView () главного окна.Я использую сервис диалога, чтобы мой код удовлетворял шаблону проектирования MVVM.И я использую фабрику, чтобы напрямую не создавать объект класса модели представления непосредственно в методе, который я хочу протестировать.Фабрика просто создает и возвращает объект, запрашивая его.

При запуске тест проходит.

Как это может произойти, если я не настроил метод CreateEditViewModel для ViewModelFactoryMock?Что именно возвращается методом при вызове во время теста?Или в более широком смысле: насколько сходные объекты похожи на фактический объект?Когда мне нужно настроить методы для объектов, которые можно использовать?

vm.OpenEditView ()

public void OpenEditView()
    {
        EditViewModel viewModel = viewModelFactory.CreateEditViewModel(Argument1, Argument2, ...);
        bool? result = dialogService.ShowDialog(viewModel);
    }

Юнит-тест:

[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void TestMethod1()
    {
        // Arrange
        var DialogServiceMock = new Mock<IDialogService>();

        var ViewModelFactoryMock = new Mock<IViewModelFactory>();

        DialogServiceMock
            .Setup(x => x.ShowDialog(It.IsAny<EditViewModel>()))
            .Returns(true)
            .Verifiable();

        MainWindowViewModel vm = new MainWindowViewModel(DialogServiceMock.Object, ViewModelFactoryMock.Object);

        // Act
        vm.OpenEditView();

        // Assert
        DialogServiceMock.Verify(mock => mock.ShowDialog(It.IsAny<EditViewModel>()));
    }
}

IViewModelFactory

    public interface IViewModelFactory
{
    EditViewModel CreateEditViewModel(Argument1, Argument2, ...);
}

Ответы [ 2 ]

0 голосов
/ 03 декабря 2018

Насколько макетированные объекты похожи на реальный объект?

Нет, скорее, это макетированная установка.MOQ - это система имитации на основе Dynamic Proxy .Поэтому, когда вы создаете макет (заглушку) интерфейса (интерфейс, API которого вы хотите смоделировать), он создает прокси этого интерфейса, в общем, он создает класс прокси, наследуя фактический тип / интерфейс в mock и overrideконкретный метод (поэтому MOQ может работать только с методом virtual или abstract).

Таким образом, когда вызывается фактический метод API, ваш тестовый исполнитель обязательно вызывает метод перехватчика (метод Setup)с любым аргументом, который вы передаете, а не с фактическим аргументом.

0 голосов
/ 03 декабря 2018

Как это может произойти, если я не настроил метод CreateEditViewModel для ViewModelFactoryMock?

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

Что именно возвращаетсяметодом, когда он вызывается во время теста?

В этом случае значение viewModel равно null , поскольку на макете не было установлено ожидание.

Тест проходит, потому что проверка

DialogServiceMock.Verify(mock => mock.ShowDialog(It.IsAny<EditViewModel>()));

ожидает It.IsAny<EditViewModel>(), который может включать null .

Если вы хотите проверить фактический экземпляр, то вы можете создатьодин и настроить макет вести себя, как ожидалось.Предполагая, что EditViewModel не является sealed

[TestMethod]
public void TestMethod1()
{
    // Arrange
    var DialogServiceMock = new Mock<IDialogService>();

    var ViewModelFactoryMock = new Mock<IViewModelFactory>();

    var viewModel = Mock.Of<EditViewModel>(); // Or new EditViewModel(...);

    ViewModelFactoryMock
        .Setup(_ => _.CreateEditViewModel(It.IsAny<Argument1>(),....));
        .Returns(viewModel);

    DialogServiceMock
        .Setup(x => x.ShowDialog(It.IsAny<EditViewModel>()))
        .Returns(true)
        .Verifiable();

    MainWindowViewModel vm = new MainWindowViewModel(DialogServiceMock.Object, ViewModelFactoryMock.Object);

    // Act
    vm.OpenEditView();

    // Assert

    //verify that the mocked view model was actually used.
    DialogServiceMock.Verify(mock => mock.ShowDialog(viewModel));
}

Насколько максируемые объекты похожи на реальный объект?

Они (макеты) являются производными от базового типа, поэтому они являются реализациями реального объекта / интерфейса

Когда мне нужно настроить методы макетируемых объектов?

Только когда их поведение необходимо для выполнения теста до завершения.

...