Как мне прочитать эти выражения установки moq? - PullRequest
0 голосов
/ 03 апреля 2019

Альтернативное название: Что означают эти выражения?

РЕДАКТИРОВАТЬ: Этот пост почти помог, но только объяснил разницу между двумя функциями настройки, а не как их читать.

Я изучаю, как использовать moq и собираю базовые тренинги для своей команды, и после просмотра этого видео и поиска других сообщений stackoverflow (среди прочих), Я думаю, что понимаю это достаточно хорошо, чтобы использовать его, но только в том смысле, что «это именно так, как это делается». У меня нет оправдания или возможности объяснить синтаксис. Пожалуйста, помогите.

Для справки, я понимаю использование шаблонов C # и выражений, а также функций, действий и событий в одиночку, но смешивать их вместе? Мета реальна.

Рассмотрим следующий фрагмент кода из одного из модульных тестов видеодемонстрации: Should_Mock_Events_Based_On_Action() ( источник модульного тестирования , источник IRepo ):

var mockRepo = new Mock<IRepo>();
mockRepo.Setup(x => x.AddRecord(null))
    .Raises(m => m.FailedDatabaseRequest += null, this, EventArgs.Empty);
  1. Кажется, что функция Setup(...) гласит: «Установите функцию, которая принимает IRepo, а затем вызывает AddRecord(...) с помощью null». Но эта установка копирует IRepo.AddRecord(...), что не является выражением. Каким-то образом это переводится внутри макета на «Настройте функцию для IRepo, называемую AddRecord(...), такую, что, когда она принимает null, она ведет себя определенным образом». Но так не читается. Как это должно читаться? Каким-то образом выражение каким-то образом превращается в реальный вызов функции.

  2. Функция Raises(...) действительно смущает меня. Похоже, он говорит: «Ранее настроенная функция вызывает событие, которое принимает IRepo и добавляет null в свой обработчик событий». И ... как-то так происходит событие? Эта операция += null ничего не возвращает, и я не смог понять, как это понимается как событие, которое ищет этот обработчик. Я нашел несколько статей и SO сообщений, которые показывают, что это именно так, как это делается, но ни одна из них (которые я нашел еще) не объясняет почему . Как это читать?

Ответы [ 2 ]

1 голос
/ 03 апреля 2019

Скажем, у меня есть интерфейс ITest, который имеет один метод:

public interface ITest
{
    bool IsEvent(int input);
}

Затем я хочу высмеять это - и помните, сейчас у меня есть нет фактический конкретный класс.

        var mock = new Mock<ITest>();

Теперь я хочу установить 2 звонка:

        mock.Setup(x => x.IsEven(1)).Returns(false);
        mock.Setup(x => x.IsEven(2)).Returns(true);

Это говорит фиктивному объекту:

Если ваш метод IsEven вызывается со значением 1, вернуть false.
Если ваш метод IsEven вызывается со значением 2, верните true.

Вы настраиваете поведение на своем объекте.

Итак, если я сделаю это в коде:

        var for1 = mock.Object.IsEven(1);
        var for2 = mock.Object.IsEven(2);

Переменная for1 будет ложной, а for2 будет истинной, потому что я сказал фиктивному объекту, что именно он должен делать. Параметр для Setup фактически говорит: «Это поведение, за которым я хочу, чтобы вы следили, и я скажу вам, что делать». В моем случае я использую метод Returns, чтобы указать, что фактически возвращается из моего фиктивного объекта в этом конкретном случае.

В вашем конкретном случае:

        mockRepo.Setup(x => x.AddRecord(null))
            .Raises(m => m.FailedDatabaseRequest += null, this, EventArgs.Empty);

Это говорит о высмеянном объекте

Если кто-то вызывает метод AddRecord с параметром null, тогда вызвать событие типа FailedDatabaseRequest

Для получения дополнительной информации о методе Raises см. Документацию по быстрому запуску Moq для событий здесь.

Для более глубокого просмотра событий с помощью Moq есть некоторая полезная информация здесь - в частности, речь идет о += null, который вызывает у вас некоторую путаницу:

Чтобы вызвать событие из фиктивного объекта, мы используем его метод Raise. это принимает два параметра. Первое - это лямбда-выражение, которое включает пустой подписчик события для события, чтобы поднять. Хотя не то самый элегантный синтаксис, это необходимо, чтобы позволить Moq понять, как событие используется. Второй параметр предоставляет аргументы события это будет включено в событие.

0 голосов
/ 05 апреля 2019

Отвечая на свой вопрос.

Моя путаница коренится в том, что я не понимаю, как работают выражения C # (не лямбда-выражения, а конкретно Expression<>). Они представляют собой теорию компилятора (в частности, «деревья выражений») и могут использоваться для декомпозиции лямбда-выражений на части, включая параметры, константы, бинарные операторы и другие. Moq использует это и использует части для создания своего собственного объекта с указанной функциональностью + вспомогательный код для проверки. Я не знал, что C # может сделать это.

MSDN Expression

Серия учебников, которые помогли мне запутаться: Деревья выражений C #

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