Func delegates and properties: not interchangeable


Func delegates and properties: not interchangeable

It’s not uncommon to use methods with dozens of overloads, especially when using third party libraries such as Moq, which is great because that way we can often find one which suits our needs. Some of them can be very similar, and we often end up not knowing exactly which one we are using, but we are getting the job done. That’s no problem at all, but sometimes, a slight difference can heavily influence the outcome.

Let’s take Moq’s Setup method, which recently gave me a bit of work. For those unfamiliar with it, this method allows us to extensively mock a method’s behavior, such as its return, callback, have it throw an exception, and a lot more. It’s really powerful, and if you are planning on leveling up your unit testing skills, it’s a fundamental tool to have at your disposal.

So, as I mentioned before, Moq allows you to setup what a method shall return when invoked. There are overloads available for us, including one which accepts a value, and one which takes a Func delegate, meaning that we could write our setup call as below:

// First approach: Using a property
fbiSecretsMock.Setup(x => x.NextLottoJackpotDate).Returns(DateTime.Now);

// Second approach: Using a func delegate
fbiSecretsMock.Setup(x => x.NextLottoJackpotDate).Returns(() => DateTime.Now);

In both ways, it will return the current time. Seems simple, with no tricks or shenanigans right? The thing is, it depends. When we pass only the property as a parameter to the Return function, it will store the result of DateTime.Now and return the same value every time, while if we pass the Func delegate, it will always reevaluate it. That means that if we were to use the first approach 10 times during the execution of our unit test, we would the same value 10 times, and with the second approach, we would get 10 different values.

So, when should you use one or another? I’m pretty sure that usually it doesn’t really matter, with any of them you will get your expected result. But it is good to be aware of the difference between them, so you don’t end up banging your head on the keyboard, just as yours truly did a while ago.