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.