4

I am currently using the Moq library for unit testing. Moq gives me the ability to register callbacks before and after method invocation on a mocked object like so:

Mock<IMyClass> mock = new Mock<IMyClass>();
mock.Setup(o => o.MyMethod())
  .Callback(() => Console.WriteLine("BEFORE!"))
  .Returns(true)
  .Callback(() => Console.WriteLine("AFTER!"));

However, if MyMethod does not return a value (i.e. it has a void return type), then I can only setup a single Callback like so:

mock.Setup(o => o.MyMethod())
  .Callback(() => Console.WriteLine("BEFORE!"));

As noted in the code, this callback happens BEFORE the method is invoked. There don't seem to be any other options for specifying a second callback for after the method is invoked.

Is this possible? There doesn't seem to be anything in the documentation about it. Am I missing something?

Kevin Craft
  • 849
  • 8
  • 18
  • I'm not sure what you mean by HandleMessage isn't finished. The *only* thing HandleMessage is doing is calling `waitHandle.Reset`. `WaitOne` waits for the handle to be set, if you start with your `ManualResetEvent` in the signaled state, it's possible the test thread would get past `WaitOne` before the `HandleMessage` gets called. I would think you would want to start with your `ManualResetEvent` in an unsignaled state, then your handler would call `Set`. But if you're trying to test some behavior that occurs after HandleMessage is called, you need another approach. – Erik Feb 25 '15 at 19:36
  • Ha...I was misusing ManualResetEvent. Derp. Everything works now. I'm going to remove the details of my specific case since they will confuse anyone else who finds this question. Thank you! – Kevin Craft Feb 25 '15 at 19:50

1 Answers1

5

It's not possible.

The return value of Callback is IReturnsThrows, which is a combination of the IReturns interface with Returns methods, and IThrows interface with Throws methods. You can follow a Returns with a Callback because the return value of Returns is IReturnResult which implements ICallback.

What exactly are you trying to accomplish? The callbacks in your example don't really occur before and after the method are called, they are simply executed in order as steps when the method is called. Your before callback is executed before the return value is computed, then your after callback is done after that. There is no point to doing two callbacks in a row since you can just combine them into a single callback.

Erik
  • 5,355
  • 25
  • 39
  • "The callbacks in your example don't really occur before and after the method is called" [Are you sure?](https://github.com/Moq/moq4/wiki/Quickstart#callbacks) (Hint: take a look at the last example.) – rsenna Feb 25 '15 at 19:20
  • 2
    Yes, the callbacks occur before and after the `Returns` statement is evaluated (see the text in the `Console.WriteLine` call in the callbacks in the example). They are steps executed when the method is called. There is no before/after the method is actually called, when code consuming the mock object calls `someObj.MyMethod()` that *is* the method call. – Erik Feb 25 '15 at 19:28
  • @Erik again, I'm not disagreeing about *how* the expected behavior happens. Yes, I believe you're right, the callbacks order is defined by the evaluation of the `Returns` statement. Still, for all practical purposes, *what* happens is exactly what the OP (and Moq's documentation for that matter) described: the first callback happens *before* the mocked method call, and the second one *after*. – rsenna Feb 25 '15 at 19:44
  • 2
    @rsenna, no I disagree. The `Returns` method by itself is not the method body, when you put `Callback`, `Returns`, `Throws`, etc. those *are* the implementation of the mocked method call. From the perspective of code that calls the method, all those things happen as part of the method call. Something that happens before or after a method call is something that is not part of that method call and is done outside the call. – Erik Feb 25 '15 at 20:50