.net 你能帮我理解起订量回调吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2833162/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 14:18:13  来源:igfitidea点击:

Can you help me understand Moq Callback?

.netmoq

提问by user9969

Using Moq and looked at Callbackbut I have not been able to find a simple example to understand how to use it.

使用 Moq 并查看了Callback但我一直无法找到一个简单的示例来理解如何使用它。

Do you have a small working snippet which clearly explain how and when to use it?

您是否有一个小的工作片段可以清楚地解释如何以及何时使用它?

采纳答案by Ruben Bartelink

Hard to beat https://github.com/Moq/moq4/wiki/Quickstart

难以击败https://github.com/Moq/moq4/wiki/Quickstart

If that's not clear enough, I'd call that a doc bug...

如果这还不够清楚,我会称其为文档错误...

EDIT: In response to your clarification...

编辑:为了回应你的澄清......

For each mocked method Setupyou perform, you get to indicate things like:

对于Setup您执行的每个模拟方法,您可以指出以下内容:

  • constraints on inputs
  • the value for / way in which the return value (if there is one) is to be derived
  • 对输入的限制
  • / 返回值(如果有)的推导方式的值

The .Callbackmechanism says "I can't describe it right now, but when a call shaped like this happens, call me back and I'll do what needs to be done". As part of the same fluent call chain, you get to control the result to return (if any) via .Returns". In the QS examples, an example is that they make the value being returned increase each time.

.Callback机制说“我现在无法描述它,但是当发生这样的呼叫时,给我回电,我会做需要做的事情”。作为同一流畅调用链的一部分,您可以通过.Returns“控制返回的结果(如果有)。在 QS 示例中,一个示例是它们使每次返回的值增加。

In general, you won't need a mechanism like this very often (xUnit Test Patterns have terms for antipatterns of the ilk Conditional Logic In Tests), and if there's any simpler or built-in way to establish what you need, it should be used in preference.

一般来说,你不会经常需要这样的机制(xUnit 测试模式有类似条件逻辑在测试中的反模式的术语),如果有任何更简单或内置的方法来建立你需要的东西,它应该是优先使用。

Part 3 of 4 in Justin Etheredge's Moq seriescovers it, and there's another example of callbacks here

Justin Etheredge 的 Moq 系列 4 部分中的第 3 部分介绍了它,这里还有另一个回调示例

A simple example of a callback can be found at Using Callbacks with Moqpost.

一个简单的回调示例可以在使用回调与 Moq帖子中找到。

回答by Jeff Hall

Here's an example of using a callback to test an entity sent to a Data Service that handles an insert.

下面是使用回调测试发送到处理插入的数据服务的实体的示例。

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

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

Alternative generic method syntax:

替代泛型方法语法:

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

Then you can test something like

然后你可以测试类似的东西

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

回答by Shaun Luttin

There are two types of Callbackin moq. One happens before the call returns; the other happens after the call returns.

Callbackmoq有两种类型。一个发生在调用返回之前;另一个发生在调用返回之后。

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}");
    });

In both callbacks, we can:

在这两个回调中,我们可以:

  1. inspect method arguments
  2. capture method arguemnts
  3. change contextual state
  1. 检查方法参数
  2. 捕获方法论证
  3. 改变上下文状态

回答by Ohad Schneider

Callbackis simply a means to execute any custom code you want when a call is made to one of the mock's methods. Here's a simple example:

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

I recently ran into an interesting use case for it. Suppose you expect some calls to your mock, but they happen concurrently. So you have no way of knowing the order in which they'd get called, but you want to know the calls you expected did take place (irrespective of order). You can do something like this:

我最近遇到了一个有趣的用例。假设您期望对您的模拟进行一些调用,但它们同时发生。所以你无法知道他们被调用的顺序,但你想知道你期望的调用确实发生了(不管顺序)。你可以这样做:

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 don't get confused by the misleading "before Returns" and "after Returns" distinction. It is merely a technical distinction of whether your custom code will run after Returnshas been evaluated or before. In the eyes of the caller, both will run before the value is returned. Indeed, if the method is void-returning you can't even call Returnsand yet it works the same. For more information see https://stackoverflow.com/a/28727099/67824.

顺便说一句,不要被误导性的“之前Returns”和“之后Returns”区别所迷惑。这只是您的自定义代码Returns是在评估之后还是之前运行的技术区别。在调用者的眼中,两者都会在返回值之前运行。事实上,如果方法是void-returning 你甚至不能调用Returns,但它的工作原理是一样的。有关更多信息,请参阅https://stackoverflow.com/a/28727099/67824

回答by Frank Bryce

On top of the other good answers here, I've used it to perform logic before throwing an exception. For instance, I needed to store all objects that were passed to a method for later verification, and that method (in some test cases) needed to throw an exception. Calling .Throws(...)on Mock.Setup(...)overrides the Callback()action and never calls it. However, by throwing an exception within the Callback, you can still do all of the good stuff that a callback has to offer, and still throw an exception.

除了这里的其他好答案之外,我还使用它在抛出异常之前执行逻辑。例如,我需要存储传递给方法的所有对象以供以后验证,并且该方法(在某些测试用例中)需要抛出异常。调用.Throws(...)Mock.Setup(...)覆盖的Callback()行动,并永远不会调用它。但是,通过在回调中抛出异常,您仍然可以执行回调必须提供的所有好东西,并且仍然抛出异常。