1

I use a Util-Method that is an Extension-method delaying It.*-calls until the Setup (using the result of an It.*-call stored in a variable doesn't seem to work).

However, I noticed that when I call the Func<string> message with message(), the Setup will not work properly. When using message.Invoke(), it works just as I expect.

As far as I understand, message() should be syntactic sugar for message.Invoke(), but then why do they behave differently?


I do believe that has something to do with the Moq-Framework, that's why I tagged this . Something like Func<string> f = ()=>"test"; f(); returns a string. Moq does lots of magic with It.*, Mock<> and so on, maybe I interfered with it somehow.


Following example:

public interface ILog 
{
    void Debug(string message, Exception exception = null);
}

public class LogUtils
{
    public static void Debug(this Mock<ILog> mock, string message, Exception exception = null)
    {
        mock.Debug(() => message, () => exception);
    }

    public static void Debug(this Mock<ILog> mock, Func<string> message, Func<Exception> exception)
    {
        // NOT working line
        mock.Setup(logger => logger.Debug(message(), exception()));

        // Working line
        mock.Setup(logger => logger.Debug(message.Invoke(), exception.Invoke()));
    }
}


// Test Method
public void TestMethod()
{
    Mock<ILog> logger = new Mock<ILog>(MockBehavior.Strict);

    // Setup logger to accept any input by using It.IsAny<>-MethodGroup
    logger.Debug(It.IsAny<string>, It.IsAny<Exception>);

    // Fails with no corresponding setup
    logger.Object.Debug("Test");
}
JFBM
  • 944
  • 1
  • 11
  • 24
  • This appears to be an [XY problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). What is the ultimate goal you are trying to achieve? – Nkosi Oct 27 '17 at 14:11
  • @Nkosi I read that `func()` and `func.Invoke()` are the same (after desugaring). I experience it's not. As I can only break it in a specific way, my code-example is a bit bigger. To restate the question: *As far as I understand, `message()` should be syntactic sugar for `message.Invoke()`, but then why do they behave differently?* – JFBM Oct 27 '17 at 14:18
  • They are the same but `func()` in `mock.Setup(logger => logger.Debug(message(), exception()));` is an expression while `func.Invoke()` represents a constant in the expression when compiled. It has to do with how Moq interprets the setup expression. – Nkosi Oct 27 '17 at 14:22
  • What you are trying to do was not part of the expected use cases for the setup. `It.*<>()` were not meant to be used like that. They were specifically created to be interpreted in the setup expression. Not to be used as variables. Which is why I asked my original question. What purpose does delaying the setup pose. – Nkosi Oct 27 '17 at 14:30
  • @Nkosi I don't want to write `logger.Setup(l => l.Debug(..., ...))` everytime. I have other methods that take 5 arguments and return a result. Instead of having a big code-block with lots of duplication all over the place, I want to bundle it in a method. By Experiment I found out that using a `Func` to delay `It.*<>()`-Execution works. But then I stumbled about the difference of supposedly equal statements. – JFBM Oct 27 '17 at 15:15
  • Okay, I just got the semantic difference between `func()` and `func.Invoke()` *in this lambda-context*. `func()` evaluates and puts the result in the lambda, which is then handed to Moq. `func.Invoke()` doesn't get executed until Moq runs the setup, where `It.*<>()` becomes meaningfull. The difference is *when* `func` is invoked, correct? – JFBM Oct 27 '17 at 15:30

0 Answers0