Как смоделировать метод службы, указав имя метода в виде строки - PullRequest
3 голосов
/ 03 июня 2019

Я хочу смоделировать метод службы, указав его имя в виде строки:

public interface IService 
{
    SomeType SomeMethod(int a, int b);
}

...
var service = new Mock<IService>();
string methodName = nameof(IService.SomeMethod);

service.Setup(s => s."methodName"(It.IsAny<int>(), It.IsAny<int>())
    .Callback<int, int>(...faking is not related);

Я знаю, что должен каким-то образом использовать Expression, но не представляю, как сделать это выражение на основе IService и с параметрами It.IsAny.

1 Ответ

2 голосов
/ 03 июня 2019

Вы можете построить выражение, например, следующим образом:

    private static Expression<Action<T>> ConstructMethodCallExpressionWithItIsAnyOnAllArguments<T>(string mehodName)
    {
        var methodInfo = typeof(T).GetMethod(mehodName);

        var argumentExpression = Expression.Parameter(typeof(T));

        var methodExpression = Expression.Call(
            argumentExpression,
            methodInfo,
            methodInfo.GetParameters().Select(pi => Expression.Call(
                typeof(It), "IsAny", new Type[] { pi.ParameterType }, new Expression[0])));

        var result = Expression.Lambda<Action<T>>(
            methodExpression,
            argumentExpression);
        return result; //E.g.: Expression<Action<IService>>(s => s.SomeMethod(It.IsAny<int>(), It.IsAny<int>())
    }

Использование:

    var service = new Mock<IService>();
    string methodName = nameof(IService.SomeMethod);
    service.Setup(ConstructMethodCallExpressionWithItIsAnyOnAllArguments<IService>(methodName))
            .Callback<int, int>((x, y) => { ... });

А если необходимо выражение Func:

    private static Expression<Func<T, TResult>> ConstructMethodCallExpressionFunc<T, TResult>(string mehodName)
    {
        var methodInfo = typeof(T).GetMethod(mehodName);

        var argumentExpression = Expression.Parameter(typeof(T));

        var methodExpression = Expression.Call(
            argumentExpression,
            methodInfo,
            methodInfo.GetParameters().Select(pi => Expression.Call(
                typeof(It), "IsAny", new Type[] { pi.ParameterType }, new Expression[0])));

        var result = Expression.Lambda<Func<T, TResult>>(
            methodExpression,
            argumentExpression);
        return result; //E.g.: Expression<Func<IService, string>>(s => s.SomeMethod(It.IsAny<int>(), It.IsAny<int>())
    }

При использовании:

    var service = new Mock<IService>();
    string methodName = nameof(IService.SomeMethod);

    service.Setup(ConstructMethodCallExpressionFunc<IService, string>(methodName))
           .Returns<int, int>((x, y) => (x.ToString() + y.ToString()));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...