Converting an MOQ property setup to FakeItEasy

288 views Asked by At

In one of the "builders" we have following method that uses MOQ SetupGet. I tried re-writing it to use FakeItEasy, but there does not seem to be a way to do it, as WithReturnType provides only generic version, where type has to be known up front. There is no non-generic version, that takes in actual type determined at the run time.

Granted I've spent whole 30 min. on FakeItEasy, so there might be a better way...

Original method with MOQ

public void With<TProperty>(Expression<Func<TCommand, TProperty>> expression, TProperty value)
{
      CommandFake.SetupGet(expression).Returns(value);
}

With my limited knowledge of expressions I tried re-writing it to use FakeItEasy but I cannot set the return value.

    public void With<TProperty>(Expression<Func<TCommand, TProperty>> expression, TProperty value)
    {
        var methodName = string.Empty;

        var e = (LambdaExpression) expression;

        if (e.Body.NodeType == ExpressionType.MemberAccess)
        {
            var memberInfo = ((MemberExpression) e.Body).Member;
            if (memberInfo.MemberType == MemberTypes.Property)
            {
                methodName = "get_" + memberInfo.Name;
            }
            //A.CallTo(CommandFake).Where(call => call.Method.Name == methodName)
            //    .WithReturnType<>()
        }

        //CommandFake.SetupGet(expression).Returns(value);
    }

Are there any other ways to do this? I am not stuck on this method signature for With.

This would also work

 public void With(Expression<Action<TCommand>> expression)

so that one could do

With(x=>x.someProp=someValue)
1

There are 1 answers

2
Blair Conrad On BEST ANSWER

I'm not a Moq user, but it looks like SetupGet just defines an action on a property get. This seems to be equivalent to A.CallTo in FakeItEasy.

Is there a reason not to just use

A.CallTo(() => CommandFake.TheProperty).Returns(value));

?

If you really want to be able to call something like

With(f => f.TheProperty, 7);

You could (working from your example) use

public void With<TProperty>(Expression<Func<TCommand, TProperty>> expression, TProperty value)
{
    var methodName = string.Empty;

    var e = (LambdaExpression)expression;

    if (e.Body.NodeType == ExpressionType.MemberAccess)
    {
        var memberInfo = ((MemberExpression)e.Body).Member;
        if (memberInfo.MemberType == MemberTypes.Property)
        {
            methodName = "get_" + memberInfo.Name;
        }
        A.CallTo(CommandFake).Where(call => call.Method.Name == methodName)
            .WithReturnType<TProperty>()
            .Returns(value);
    }
}

Or even consider just using the property's method outright, instead of the name:

public void With<TProperty>(Expression<Func<TCommand, TProperty>> expression, TProperty value)
{
    var e = (LambdaExpression)expression;

    if (e.Body.NodeType == ExpressionType.MemberAccess)
    {
        var memberInfo = ((MemberExpression)e.Body).Member;
        if (memberInfo.MemberType == MemberTypes.Property)
        {
            A.CallTo(CommandFake).Where(call =>
                        call.Method == ((PropertyInfo)memberInfo).GetMethod)
                .WithReturnType<TProperty>()
                .Returns(value);
        }
    }
}