Проверка исключений в методе закрытого делегата - PullRequest
1 голос
/ 08 марта 2020

Я разрабатываю приложение WPF в формате MVVM, и у меня возникла проблема, как проверить, что это исключение было выдано, когда сообщение было отправлено другой моделью представления. Я использую nUnit для модульного тестирования.

Я пытаюсь проверить, что делегат создает исключение, когда объект, отправленный через мессенджер, имеет значение null.

Пожалуйста, найдите простой код ниже
CTOR (все зависимости вводятся с использованием Autofa c)

    public ManagerViewModel (IMessenger messenger)
    {
       messenger.Register<Person> (this, OnPersonSent)
    }

Делегат

    private void OnPersonSent()
    {
       if(Person is null) throw new ArgumentNullException();
    }


Юнит-тест
Когда я пытаюсь утверждать, как показано ниже, он не улавливает исключения. Ситуация такова, что когда мессенджер отправляет сообщение, метод OnPersonSent должен генерировать исключение - но как его перехватить, используя Assert.Throws, если это утверждение перехватывает только выбросы исключения методом, переданным в лямбда-выражении (если я ошибаюсь, поправьте меня) , Тестовый пример ниже:

    [SetUp]
    public void SetUp()
    {
      messenger = new Messenger() // MVVMLight messenger
      sut = new ManagerViewModel(messenger)
    }

Ниже в лямбда-выражении я отправляю нулевой объект, чтобы вызвать исключение делегатом, который указан выше

    [Test] 
    public void OnPersonSent_WhenNull_ThrowsException()
    {    
           Assert.Throws<ArgumentNullException>(()=>messenger.Send((Person)null));
    }

Большое спасибо за Ваша помощь.

PS. Конечно, этот случай упрощен, чтобы ясно показать проблему

1 Ответ

1 голос
/ 10 марта 2020

Просмотрите следующий минимальный пример, чтобы увидеть, как можно протестировать вызов делегата на ожидаемое поведение

Примечание: (с использованием MOQ-фреймворка для симуляции зависимостей.)

[TestClass]
public class MyTestClass {
    [TestMethod]
    public void OnPersonSent_WhenNull_ThrowsException() {
        //Arrange
        var mock = new Mock<IMessenger>();
        Action<Person> callback = null;
        //setup the mock so the delegate can be captured when registered
        mock
            .Setup(_ => _.Register(It.IsAny<object>(), It.IsAny<Action<Person>>(), It.IsAny<bool>()))
            .Callback((object obj, Action<Person> action, bool _) => {
                callback = action; //<--
            });

        //Act
        //create view model to invoke register and capture callback in mock
        var sut = new ManagerViewModel(mock.Object);

        //Assert
        Assert.IsNotNull(callback);
        Assert.ThrowsException<ArgumentNullException>(() => callback(null));
    }
}

public class ManagerViewModel {
    public ManagerViewModel(IMessenger messenger) {
        messenger.Register<Person>(this, OnPersonSent);
    }

    private void OnPersonSent(Person person) {
        if (person is null) throw new ArgumentNullException();
    }
}

internal class Person {
}

Макет мессенджера был создан и настроен на ожидание вызова соответствующего Register члена. Макет предназначен для захвата метода делегата, предоставленного в конструкторе класса субъекта.

После того, как делегат захвачен, его можно вызвать и установить ожидаемое поведение.

Вызов делегата в test аналогичен тому, когда фактический мессенджер вызывает зарегистрированных делегатов при вызове Send.

Показанный выше подход изолирует вызов в модульном тесте.

Обратите внимание, что в приведенном выше тесте используется MSTest по умолчанию, но его можно легко применить к другим средам тестирования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...