Skip to content

Commit

Permalink
fix #1188
Browse files Browse the repository at this point in the history
  • Loading branch information
tonyhallett committed Jul 22, 2021
1 parent 9e148f6 commit ae588a4
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 18 deletions.
64 changes: 47 additions & 17 deletions src/Moq/Protected/ProtectedMock.cs
Expand Up @@ -467,26 +467,15 @@ private static Type[] ToArgTypes(object[] args)
{
types[index] = ((MethodCallExpression)expr).Method.ReturnType;
}
else if(ItRefAnyField(expr) is var itRefAnyField && itRefAnyField != null)
{
types[index] = itRefAnyField.FieldType.MakeByRefType();
}
else if (expr.NodeType == ExpressionType.MemberAccess)
{
var member = (MemberExpression)expr;
if (member.Member is FieldInfo field)
{
// Test for special case: `It.Ref<TValue>.IsAny`
if (field.Name == nameof(It.Ref<object>.IsAny))
{
var fieldDeclaringType = field.DeclaringType;
if (fieldDeclaringType.IsGenericType)
{
var fieldDeclaringTypeDefinition = fieldDeclaringType.GetGenericTypeDefinition();
if (fieldDeclaringTypeDefinition == typeof(It.Ref<>))
{
types[index] = field.FieldType.MakeByRefType();
continue;
}
}
}

types[index] = field.FieldType;
}
else if (member.Member is PropertyInfo property)
Expand All @@ -510,16 +499,57 @@ private static Type[] ToArgTypes(object[] args)
return types;
}

private static FieldInfo ItRefAnyField(Expression expr)
{
FieldInfo itRefAnyField = null;

if (expr.NodeType == ExpressionType.MemberAccess)
{
var member = (MemberExpression)expr;
if (member.Member is FieldInfo field)
{
if (field.Name == nameof(It.Ref<object>.IsAny))
{
var fieldDeclaringType = field.DeclaringType;
if (fieldDeclaringType.IsGenericType)
{
var fieldDeclaringTypeDefinition = fieldDeclaringType.GetGenericTypeDefinition();
if (fieldDeclaringTypeDefinition == typeof(It.Ref<>))
{
itRefAnyField = field;
}
}
}
}
}

return itRefAnyField;
}

private static Expression ToExpressionArg(Type type, object arg)
{
if (arg is LambdaExpression lambda)
if (arg is LambdaExpression lambda && !typeof(LambdaExpression).IsAssignableFrom(type))
{
return lambda.Body;
}

if (arg is Expression expression)
{
return expression;
if (!typeof(Expression).IsAssignableFrom(type))
{
return expression;
}

if (expression.IsMatch(out _))
{
return expression;
}

if (ItRefAnyField(expression) != null)
{
return expression;
}

}

return Expression.Constant(arg, type);
Expand Down
25 changes: 24 additions & 1 deletion tests/Moq.Tests/ProtectedMockFixture.cs
Expand Up @@ -2,7 +2,7 @@
// All rights reserved. Licensed under the BSD 3-Clause License; see License.txt.

using System;

using System.Linq.Expressions;
using Moq.Protected;

using Xunit;
Expand Down Expand Up @@ -855,6 +855,23 @@ public void DoesNotThrowIfVerifySetPropertyTimesReached()
mock.Protected().VerifySet<string>("ProtectedValue", Times.Exactly(2), ItExpr.IsAny<string>());
}

[Fact]
public void SetupShouldWorkWithExpressionTypes()
{
var mock = new Mock<FooBase>();

var expression = Expression.Constant(1);
ConstantExpression setExpression = null;
mock.Protected().SetupSet<ConstantExpression>("ExpressionProperty", expression).Callback(expr => setExpression = expr);
mock.Object.SetExpressionProperty(expression);
Assert.Equal(expression, setExpression);

ConstantExpression setExpression2 = null;
mock.Protected().SetupSet<ConstantExpression>("ExpressionProperty", ItExpr.Is<ConstantExpression>( e => (int)e.Value == 2)).Callback(expr => setExpression2 = expr);
mock.Object.SetExpressionProperty(Expression.Constant(2));
Assert.NotNull(setExpression2);
}

public class MethodOverloads
{
public void ExecuteDo(int a, int b)
Expand Down Expand Up @@ -952,6 +969,12 @@ protected virtual FooBase Overloaded(MyDerived myBase)

public class FooBase
{
protected virtual ConstantExpression ExpressionProperty { get; set; }
public void SetExpressionProperty(ConstantExpression expression)
{
ExpressionProperty = expression;
}

public virtual string PublicValue { get; set; }

protected internal virtual string ProtectedInternalValue { get; set; }
Expand Down

0 comments on commit ae588a4

Please sign in to comment.