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}"); });в обоих обратных вызовах мы можем:
- проверить аргументы метода
- метод захвата arguemnts
- изменить контекстное состояние
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(...)onMock.Setup(...)переопределяетCallback()действия и никогда не вызывает его. Однако, бросив исключение в обратном вызове, вы все равно можете сделать все хорошие вещи, которые может предложить обратный вызов, и все равно бросить исключение.
Comments