Используя Moq и посмотрев на Callback
, но я не смог найти простой пример, чтобы понять, как его использовать.
Есть ли у вас небольшой рабочий фрагмент, который четко объясняет, как и когда его использовать?
Используя Moq и посмотрев на Callback
, но я не смог найти простой пример, чтобы понять, как его использовать.
Есть ли у вас небольшой рабочий фрагмент, который четко объясняет, как и когда его использовать?
Тяжело бить https://github.com/Moq/moq4/wiki/Quickstart
Если это не ясно, я бы назвал это ошибкой doc...
EDIT: В ответ на ваше разъяснение...
Для каждого из насмешанного метода Setup
, который вы выполняете, вы можете указать такие вещи, как:
Механизм .Callback
говорит: "Я не могу описать его прямо сейчас, но когда возникает такой звонок, позвоните мне, и я сделаю то, что нужно сделать". В рамках одной и той же безвозвратной цепочки вызовов вы можете контролировать результат для возврата (если есть) через .Returns
". В примерах QS примером является то, что они возвращают возвращаемое значение каждый раз.
В общем, вам не понадобится такой механизм, как это очень часто (xUnit Test Patterns имеет термины для antipatterns Ilk Conditional Logic In Tests), и если есть более простой или встроенный способ установления того, что вам нужно, его следует использовать в предпочтении.
Часть 3 из 4 в серии Justin Etheredge 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");
В moq есть два типа Callback
. Один происходит до возврата вызова; другое происходит после возврата вызова.
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}");
});
В обоих обратных вызовах мы можем:
В дополнение к другим хорошим ответам здесь я использовал его для выполнения логики, прежде чем выбрасывать исключение. Например, мне нужно было сохранить все объекты, которые были переданы методу для последующей проверки, и этот метод (в некоторых тестовых случаях) должен был генерировать исключение. Вызов .Throws(...)
на Mock.Setup(...)
отменяет действие Callback()
и никогда не вызывает его. Однако, выбирая исключение в обратном вызове, вы все равно можете использовать все хорошие вещи, которые может предложить обратный вызов, и все же вызывать исключение.
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
BTW не путаются из-за вводящих в заблуждение различий "до Returns
" и "после Returns
". Это просто техническое разграничение того, будет ли ваш пользовательский код работать после того, как Returns
будет оценен или раньше. В глазах вызывающего, оба будут работать до возвращения значения. В самом деле, если метод void
-вращения, вы даже не можете вызвать Returns
, и все же он работает одинаково. Для получения дополнительной информации см. fooobar.com/info/84640/....