Skip to content

Instantly share code, notes, and snippets.

@ngocvantran
Last active November 13, 2021 17:46
Show Gist options
  • Star 15 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save ngocvantran/1c6b329e85ca29071f42 to your computer and use it in GitHub Desktop.
Save ngocvantran/1c6b329e85ca29071f42 to your computer and use it in GitHub Desktop.
Extension methods to quickly ignore arguments without repeating It.IsAny<>()
using System;
using System.Linq.Expressions;
using Moq.Language.Flow;
namespace Moq
{
public static class MoqExtensions
{
public static ISetup<T, TResult> SetupIgnoreArgs<T, TResult>(this Mock<T> mock,
Expression<Func<T, TResult>> expression)
where T : class
{
expression = new MakeAnyVisitor().VisitAndConvert(
expression, "SetupIgnoreArgs");
return mock.Setup(expression);
}
public static ISetup<T> SetupIgnoreArgs<T>(this Mock<T> mock,
Expression<Action<T>> expression)
where T : class
{
expression = new MakeAnyVisitor().VisitAndConvert(
expression, "SetupIgnoreArgs");
return mock.Setup(expression);
}
public static void VerifyIgnoreArgs<T>(this Mock<T> mock,
Expression<Action<T>> expression, Func<Times> times = null)
where T : class
{
expression = new MakeAnyVisitor().VisitAndConvert(
expression, "VerifyIgnoreArgs");
mock.Verify(expression, times ?? Times.AtLeastOnce);
}
public static void VerifyIgnoreArgs<T, TResult>(this Mock<T> mock,
Expression<Func<T, TResult>> expression, Func<Times> times = null)
where T : class
{
expression = new MakeAnyVisitor().VisitAndConvert(
expression, "VerifyIgnoreArgs");
mock.Verify(expression, times ?? Times.AtLeastOnce);
}
private class MakeAnyVisitor : ExpressionVisitor
{
protected override Expression VisitConstant(ConstantExpression node)
{
if (node.Value != null)
return base.VisitConstant(node);
var method = typeof(It)
.GetMethod("IsAny")
.MakeGenericMethod(node.Type);
return Expression.Call(method);
}
}
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using Xunit;
namespace Moq
{
public class MoqExtensionsTests
{
[Fact]
public void SetupIgnoreArgs_action_should_ignore_arguments()
{
var mock = new Mock<IDummy>();
mock
.SetupIgnoreArgs(x => x
.Execute(null, null, null))
.Verifiable();
mock.Object.Execute("dummy input",
new[] {"dummy value"},
new Dictionary<string, object>
{
{"dummy key", new object()},
});
mock.Verify();
}
[Fact]
public void SetupIgnoreArgs_function_should_ignore_arguments()
{
var mock = new Mock<IDummy>();
mock
.SetupIgnoreArgs(x => x
.Get(null, null, null))
.Verifiable();
mock.Object.Get("dummy input",
new[] {"dummy value"},
new Dictionary<string, object>
{
{"dummy key", new object()},
});
mock.Verify();
}
[Fact]
public void VerifyIgnoreArgs_action_should_ignore_arguments()
{
var mock = new Mock<IDummy>();
mock.Object.Execute("dummy input",
new[] {"dummy value"},
new Dictionary<string, object>
{
{"dummy key", new object()},
});
mock.VerifyIgnoreArgs(x => x
.Execute(null, null, null));
}
[Fact]
public void VerifyIgnoreArgs_function_should_ignore_arguments()
{
var mock = new Mock<IDummy>();
mock.Object.Get("dummy input",
new[] {"dummy value"},
new Dictionary<string, object>
{
{"dummy key", new object()},
});
mock.VerifyIgnoreArgs(x => x
.Get(null, null, null));
}
public interface IDummy
{
void Execute(string input, IList values,
IDictionary<string, object> settings);
string Get(string input, IList values,
IDictionary<string, object> settings);
}
}
}
@joelbyler
Copy link

have you tried to submit a pull request to include this yet?

@PandaWood
Copy link

Thanks, I found this doesn't work when the mock is called multiple times in the test, subsequent calls fails to return the correct result. I should provide a sample case....

@aortegadev
Copy link

Thanks :) 👍

@brunoracosta
Copy link

In my project the VerifyIgnoreArgs does't work because of the line 36 and 46

@kmcc049
Copy link

kmcc049 commented May 25, 2016

Works for me so far, thanks!

@davidvesely
Copy link

It is great. Just had to remove the check at method VisitConstant of class MakeAnyVisitor to allow calls to methods with value type arguments.

@Jacob-McKay
Copy link

I would love this if it worked, defining It.IsAny(), It.IsAny(), It.IsAny(), ... is such a PITA

@rahulbpatel
Copy link

Just curious, what is the point of the node.Value != null check on line 53? If you have a method signature like foobar(string, int, string) and called SetupIgnoreArgs(x => x.foobar(null, 0, null)) the int will not be ignored.

@Crashdummyy
Copy link

Won't work for me ...
In Test:
bool saveCalled = true; bool addCalledAfterSave = false; folderMock.SetupIgnoreArgs(f => f.set_AttributeValue(null, null)) .Callback(() => addCalledAfterSave = saveCalled);
set_AttributeValue (has 4 overloads) is called 3 times yet SetupIgnoreArgs won't get called ( addCalledAfterSave remaining false... )

@christothes
Copy link

I was inspired by your gist and created this variation.

@artkpv
Copy link

artkpv commented Nov 20, 2020

What is the license for this gist? Can I use it for a commercial project?

@ngocvantran
Copy link
Author

What is the license for this gist? Can I use it for a commercial project?

Sure, do whatever you want with it. See https://gist.github.com/7Pass/1c6b329e85ca29071f42#gistcomment-2600736 which seems to be a better version though.

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