Skip to content

Instantly share code, notes, and snippets.

@christothes
Last active February 8, 2022 15:35
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save christothes/7d57db1d16c96669ecd0218ab056a422 to your computer and use it in GitHub Desktop.
Save christothes/7d57db1d16c96669ecd0218ab056a422 to your computer and use it in GitHub Desktop.
Moq extension inspired by https://gist.github.com/7Pass/1c6b329e85ca29071f42. Allows mocks to be setup with all args as default without having to type out each one in the Setup.
public static class MoqExtensions
{
public static ISetup<T, TResult> SetupDefaultArgs<T, TResult>(this Mock<T> mock, string methodName)
where T : class
{
var method = typeof(T).GetMethod(methodName);
if(method == null)
{
throw new ArgumentException($"No method named '{methodName}' exists on type '{typeof(T).Name}'");
}
var instance = Expression.Parameter(typeof(T), "m");
var callExp = Expression.Call(instance, method, method.GetParameters().Select(p => GenerateItIsAny(p.ParameterType)));
var exp = Expression.Lambda<Func<T, TResult>>(callExp, instance);
return mock.Setup(exp);
}
private static MethodCallExpression GenerateItIsAny(Type T)
{
var ItIsAnyT = typeof(It)
.GetMethod("IsAny")
.MakeGenericMethod(T);
return Expression.Call(ItIsAnyT);
}
}
void Main()
{
var mock = new Mock<IFooContainer>();
mock.SetupDefaultArgs<IFooContainer, string>("DoBar")
.Returns<string>((s) => s);
var result = mock.Object.DoBar("it worked");
Console.WriteLine(result);
mock.SetupDefaultArgs<IFooContainer, string>("DoFoo")
.Returns<string, int, Guid>((s, i, g) => $"{s} {i} {g}");
result = mock.Object.DoFoo("it worked", 3, Guid.NewGuid());
Console.WriteLine(result);
result = mock.Object.DoFoo("it worked", 3, Guid.NewGuid());
Console.WriteLine(result);
// throws "No method named 'Invalid Method' exists on type 'IFooContainer'"
mock.SetupDefaultArgs<IFooContainer, string>("Invalid Method")
.Returns<string, int, Guid>((s, i, g) => $"{s} {i} {g}");
}
public interface IFooContainer
{
string DoFoo(string a, int b, Guid id);
string DoBar(string a);
}
@stowen-msft
Copy link

Are there certain references that are needed for this? I get an The non-generic type 'ISetup' cannot be used with type arguments compiler error from the method SetupDefaultArgs.

@stowen-msft
Copy link

Nevermind, I found it. It needs a reference to using Moq.Language.Flow;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment