Home > Back-end >  How can I mock a function delegate parameter in C#
How can I mock a function delegate parameter in C#

Time:11-19

I have a method that takes in a function parameter with a generic like this:

public async Task<T> MeasureAsync<T>(Func<Task<T>> sendFunc) {
    // implementation
}

I'm wondering how I can mock the MeasureAsync function. I tried doing something like this:

Mock.Get(_outgoingHttpOperationMeasurer)
    .Setup(x => x.MeasureAsync<T>(It.IsAny<Func<Task<T>>>()))
    .ReturnsAsync(T);

I get a compile error that T is not defined and I'm not sure exactly how to define it

CodePudding user response:

By default Moq does not require any setup. From the docs:

By default, Moq supports developers by allowing them to create unit tests without forcing them to declare every expected call.
Moq accepts all invocations and attempts to create a valid return value

Also Moq allows to customize the provided default values.

Since usually you can't(or don't need to) provide a meaningful factory for open generic type T (even if compiler allowed it) you can rely on the default mock behavior:

public interface IMyClass
{
    Task<T> MeasureAsync<T>(Func<Task<T>> sendFunc);
}

var mock = new Mock<IMyClass>();
var measureAsync = mock.Object.MeasureAsync(() => Task.FromResult(1));
var isFalse = measureAsync is null; // false

Another approach is to use It.IsAnyType (docs), though specifying return value is not easy:

mock.Setup(c => c.MeasureAsync(It.IsAny<Func<Task<It.IsAnyType>>>()))
    .Returns(new InvocationFunc(invocation =>
    {
        var arg = (Func<Task>)invocation.Arguments[0];
        return arg.Invoke();
    }));;


var measureAsync = mock.Object.MeasureAsync(() => Task.FromResult(42));

var result = await measureAsync; // 42

CodePudding user response:

T is a type. Unless you are in a scope in which that type is defined, its not gonna show up. What is probably going wrong is that you are trying to use a generic type in a scope where it isn’t defined. Make sure the function or class in which this code is written has the in it, or put it in your existing function, MeasureAsync. Otherwise, if you would like to call a generic function, you can either infer the type by saying MeasureAsync(string str) or explicitly say the type like MeasureAsync(string str). Hope this helps, if it doesn’t let me know and I will correct my answer.

  • Related