Можете ли вы помочь мне понять обратный вызов Moq?



используя Moq и посмотрел на Callback но я не смог найти простой пример, чтобы понять, как использовать его.



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

602   5  

5 ответов:

трудно победить https://github.com/Moq/moq4/wiki/Quickstart

Если это недостаточно ясно, я бы назвал это ошибкой doc...

изменить: в ответ на ваши разъяснения...

для каждого издевались метод Setup вы выполняете, вы можете указать такие вещи, как:

  • ограничения на входы
  • значение для / способ получения возвращаемого значения (если оно есть)

The .Callback говорит, что механизм "я не могу описать его прямо сейчас, но при вызове формы, как это произойдет, позвоните мне и я буду делать то, что должно быть сделано". В рамках одной и той же цепочки вызовов fluent вы можете контролировать результат для возврата (если таковой имеется) через .Returns". В примерах QS примером является то, что они заставляют возвращаемое значение увеличиваться каждый раз.

В общем, вам не понадобится такой механизм очень часто (тестовые Шаблоны xUnit имеют термины для антипаттернов условной логики ilk в Тесты), и если есть какой-либо более простой или встроенный способ установить, что вам нужно, его следует использовать в предпочтении.

Часть 3 из 4 в серии Moq Джастина Этериджа охватывает его, и здесь есть еще один пример обратного вызова

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

var mock = new Mock<IDataService>();
DataEntity insertedEntity = null;

mock.Setup(x => x.Insert(It.IsAny<DataEntity>())).Returns(1) 
           .Callback((DataEntity de) => insertedEntity = de);

альтернативного универсального метода синтаксис:

mock.Setup(x => x.Insert(It.IsAny<DataEntity>())).Returns(1) 
           .Callback<DataEntity>(de => insertedEntity = de);

тогда вы можете проверить что-то вроде

Assert.AreEqual("test", insertedEntity.Description, "Wrong Description");

есть два типа Callback в moq. Одно происходит до возвращения вызова; другое происходит после возвращения вызова.

var message = "";
mock.Setup(foo => foo.Execute(arg1: "ping", arg2: "pong"))
    .Callback((x, y) =>
    {
        message = "Rally on!";
        Console.WriteLine($"args before returns {x} {y}");
    })
    .Returns(message) // Rally on!
    .Callback((x, y) =>
    {
        message = "Rally over!";
        Console.WriteLine("arg after returns {x} {y}");
    });

в обоих обратных вызовах мы можем:

  1. проверить аргументы метода
  2. метод захвата arguemnts
  3. изменить контекстное состояние

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

public interface IFoo
{
    int Bar(bool b);
}

var mock = new Mock<IFoo>();

mock.Setup(mc => mc.Bar(It.IsAny<bool>()))
    .Callback<bool>(b => Console.WriteLine("Bar called with: " + b))
    .Returns(42);

var ret = mock.Object.Bar(true);
Console.WriteLine("Result: " + ret);

// output:
// Bar called with: True
// Result: 42

недавно я столкнулся с интересным прецедентом для него. Предположим, вы ожидаете, что некоторые вызовы на ваш макет, но они происходят одновременно. Таким образом, у вас нет способа узнать порядок, в котором они будут вызваны, но вы хотите знать, что вызовы, которые вы ожидали, имели место (независимо от порядка). Вы можете сделать что-то подобное это:

var cq = new ConcurrentQueue<bool>();
mock.Setup(f => f.Bar(It.IsAny<bool>())).Callback<bool>(cq.Enqueue);
Parallel.Invoke(() => mock.Object.Bar(true), () => mock.Object.Bar(false));
Console.WriteLine("Invocations: " + String.Join(", ", cq));

// output:
// Invocations: True, False

кстати, не смущайтесь вводящим в заблуждение "перед Returns" и "после Returns" различие. Это просто техническое различие того, будет ли ваш пользовательский код работать после Returns была оценена или раньше. В глазах вызывающего, оба будут работать до того, как значение будет возвращено. Действительно, если метод void-возвращаясь вы даже не можете позвонить Returns и все же он работает одинаково. Дополнительные сведения см. В разделе https://stackoverflow.com/a/28727099/67824.

В дополнение к другим хорошим ответам здесь, я использовал его для выполнения логики, прежде чем бросать исключение. Например, мне нужно было сохранить все объекты, которые были переданы методу для последующей проверки, и этот метод (в некоторых тестовых случаях) должен был вызвать исключение. Звоню .Throws(...) on Mock.Setup(...) переопределяет Callback() действия и никогда не вызывает его. Однако, бросив исключение в обратном вызове, вы все равно можете сделать все хорошие вещи, которые может предложить обратный вызов, и все равно бросить исключение.

Comments

    Ничего не найдено.