Moq - Is it possible to setup a mock without using It.IsAny - c#

I use Moq all the time for unit tests. Sometimes though I am mocking methods that have a lot of parameters.
Imagine a method like this:
public class WorkClient {
public void DoSomething(string itemName,
int itemCount,
ServiceClientCredential cred,
CancellationToken = default(CancellationToken){}
}
When I go to setup a mock, I end up having to do quite a lot of It.IsAny<T>(). I normally make one mocked instance per each test so I don't care about matching params.
But my mocks still look like this
var newMockClient = new Mock<WorkClient>();
newMockClient.Setup(x => x.DoSomething(
It.IsAny<string>(),
It.IsAny<int>(),
It.IsAny<ServiceClientCredential(),
It.IsAny<CancellationToken>())
.Returns(blah);
I would love to be able to just lazily instead use a LazySetup if it exists, like this.
newMockClient.Setup(x=>x.DoSomething()).Returns(blah);
Is there any lazy mode like this?

Based on this gist you can create an overload for SetupDefaultArgs which works well with void return type. You will need to add a reference to Moq.Language.Flow and System.Linq.Expressions;
public static ISetup<T> SetupDefaultArgs<T>(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<Action<T>>(callExp, instance);
return mock.Setup(exp);
}
//helper method for above
private static MethodCallExpression GenerateItIsAny(Type T)
{
var ItIsAnyT = typeof(It)
.GetMethod("IsAny")
.MakeGenericMethod(T);
return Expression.Call(ItIsAnyT);
}
So, in your case the usage would look something like this:
public interface IWorkClient
{
void DoSomething(string itemName, int itemCount,
ServiceClientCredential cred,
CancellationToken token = default(CancellationToken));
}
var mock = new Mock<IWorkClient>();
mock.SetupDefaultArgs(nameof(IWorkClient.DoSomething));
To make sure that it has been called you can do the following:
//Arrange
var mock = new Mock<IWorkClient>();
mock.SetupDefaultArgs(nameof(IWorkClient.DoSomething))
.Callback(() => Console.WriteLine("DoSomething has been called"));
var cts = new CancellationTokenSource();
//Act
mock.Object.DoSomething("1", 2, null, cts.Token);
//Assert
mock.Verify(client => client.DoSomething("1", 2, null, cts.Token), Times.Once);

Related

How to mock generic method without specifying type parameter

I have an interface
public interface ISomething
{
ISomethingElse<T> GetInstance<T>();
}
Now I want to mock this
This works:
var mock = new Mock<ISomething>();
mock.Setup(x => x.GetInstance<MyClass>()).Returns(Mock.Of<ISomethingElse<MyClass>>());
But I need a generic approach
If the return Type would just bei ISomethingElse I could write
var mock = new Mock<ISomething>();
mock.Setup(x => x.GetInstance<It.IsAnyTpye>()).Returns(Mock.Of<ISomethingElse>());
But (obviously) this doesn't work.
How can I achive this in a more generic way?
var mock = new Mock<ISomething>();
mock.Setup(x => x.GetInstance<It.IsAnyTpye>()).Returns(Mock.Of<ISomethingElse<???>>());
I figured out a good workaround.
In my case I want to test a method from MyClass that uses ISomething.
ISomething itself is tested elsewhere.
public void MyMethod(ISomething something)
{
something.GetInstance(this).Setup();
// I want to test the following code
}
I just don't want something.GetInstance(this).Setup(); to throw a NullReferenceException.
I solved it with DefaultValue = DefaultValue.Mock which does exactly what I want to achive.
new Mock<ISomething>() { DefaultValue = DefaultValue.Mock };

How do I setup MOQ to accept Any instances of a given Expression<T>?

I have the following interface that I want to mock:
public interface ISomeInterface
{
string GiveMe(Expression<Func<Person, bool>> predicate);
}
With the following Poco:
public class Person
{
public string Name { get; set; }
}
Then I am setting up my mock as:
[Test]
public void Run()
{
var expectedPredicate = It.IsAny<Expression<Func<Person, bool>>>();
var mock = new Mock<ISomeInterface>(MockBehavior.Strict);
mock
.Setup(m => m.GiveMe(expectedPredicate))
.Returns("Yo!");
var message = mock.Object.GiveMe(p => p.Name == string.Empty); // throws
}
But I am getting:
Invocation failed with mock behavior Strict. All invocations on the
mock must have a corresponding setup.
What am I missing here?
Don't assign the result of It.IsAny to an intermediate variable, use it inline:
mock.Setup(m => m.GiveMe(It.IsAny<Expression<Func<Person, bool>>>()))
.Returns("Yo!");
If you look at the Setup method, it actually takes an Expression parameter, Moq analyses this to determine what your intention is, by assigning the result of It.IsAny to an intermediate variable, Moq will not see the MethodCallExpression it is capable of understanding and instead will see a MemberExpression.
This results in Moq actually performing an equality comparison between the actual parameter and expectedPredicate variable rather than the It.IsAny check.

Substitute method in lambda expression

I am writing unit tests for a series of similar methods defined on a single interface (this is a precursor to refactoring). I'm finding that similar code shows up in multiple methods:
// Each line here shows up in a different test method.
mock.Setup(m => m.MethodA()).Returns(() => true);
mock.Setup(m => m.MethodB()).Returns(() => true);
mock.Setup(m => m.MethodC()).Returns(() => true);
I would like to create a single method into which I can pass the method to be tested, but am at a loss how to do this. I'd like something that looks like this:
// testMethod is some method defined on IMyInterface.
private Mock<IMyInterface> SetupMockObject(Func<bool> testMethod)
{
var mock = new Mock<MyInterface>();
mock.Setup(m => m.testMethod()).Returns(() => true);
return mock;
}
The call to this method would then look something like:
var configuredMockObject = SetupMockObject(MethodA);
Is this possible?
EDIT: An expression tree appears to be what I need - previously I didn't get the concept that you could pass lambda expressions around. I've pasted the solution below since it took me a bit of fiddling to figure this out, although both dBurner's and Servy's answers proved helpful.
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Moq.Language.Flow;
using System;
using System.Linq.Expressions;
namespace ExampleTest
{
[TestClass]
public class TestClass
{
private Mock<IMyInterface> _mock;
private interface IMyInterface
{
bool MethodA();
bool MethodB();
}
private ISetup<IMyInterface, bool> SetupMockObject(Expression<Func<IMyInterface,bool>> lambda)
{
var mockSetup = _mock.Setup(lambda);
return mockSetup;
}
[TestInitialize]
public void Setup()
{
_mock = new Mock<IMyInterface>();
}
[TestMethod]
public void TestMethodA()
{
SetupMockObject(i => i.MethodA()).Returns(true);
// Proceed with act and assert.
}
[TestMethod]
public void TestMethodB()
{
SetupMockObject(i => i.MethodB()).Returns(true);
// Proceed with act and assert.
}
}
}
The lambda that you pass to it needs to have a parameter of the mocked type, whereas your current parameter accepts a parameterless delegate:
public static Mock<MyInterface> SetupMockObject<T>(
Func<MyInterface, bool> testMethod)
{
var mock = new Mock<MyInterface>();
mock.Setup(testMethod).Returns(() => true);
return mock;
}
This allows you to write:
var mock = SetupMockObject(m => m.MethodA());
and have the code be equivalent to
var mock = new Mock<MyInterface>();
mock.Setup(m => m.MethodA()).Returns(() => true);
You can use expression trees for this. Your CommonTest method should have a Expression<Func<bool>> parameter.
With this parameter type you can get the method name. after this you should construct another Expression that will represent m => m.MethodFromParameter.

Pass method name from property to lambda without arguments

I am trying to achieve the following:
this.helper.Verify(i => i.SomeModule.SomeMethod);
Where:
i is a known type.
SomeModule is a public property of this type.
SomeMethod is the name of the method (passed as delegate I assume).
I would like to be able to avoid specifying the generic types in the Verify method.
Thats how far I've been able to go:
public void Verify<TProp, TResult>(
Expression<Func<KnownType, TProp>> moduleExpression,
Expression<Func<TProp, TResult>> methodExpression)
{
var moduleIdentifier = (moduleExpression.Body as MemberExpression).Member.Name;
var methodIdentifier = (methodExpression.Body as MethodCallExpression).Method.Name;
this.Verify(moduleIdentifier, methodIdentifier, state);
}
But this forces me to write the argument values for the methodExpression, like:
this.helper.Verify(
i => i.SomeModule,
m => m.SomeMethod(arg1, arg2));
Is there a way to achieve what I am looking for?
Finally I end up with a solution that requires delegates.
I need to analyze an expression that can have multiple arguments, like:
i => i.Car.Engine.Intake.Open()
I will extract the last two arguments as a "module" and "method":
public class ExpressionTools
{
public string GetLastInstanceName<TProp, TDelegate>(Expression<Func<TProp, TDelegate>> expression)
{
var unaryExpression = (UnaryExpression)expression.Body;
var methodCallExpression = (MethodCallExpression)unaryExpression.Operand;
var methodInfoExpression = (MemberExpression)methodCallExpression.Arguments.Reverse().Skip(1).First();
var instanceName = methodInfoExpression.Member.Name;
return instanceName;
}
public string GetMethodName<TProp, TDelegate>(Expression<Func<TProp, TDelegate>> expression)
{
var unaryExpression = (UnaryExpression)expression.Body;
var methodCallExpression = (MethodCallExpression)unaryExpression.Operand;
var methodInfoExpression = (ConstantExpression)methodCallExpression.Arguments.Last();
var methodInfo = (MemberInfo)methodInfoExpression.Value;
return methodInfo.Name;
}
}
Solution with delegates
A class with generics can be reused since the delegates are not necessary to analyze the expression:
public class Verifier
{
public void Verify<TDelegate>(Expression<Func<KnownType, TDelegate>> methodExpression)
{
var tools = new ExpressionTools();
var moduleName = tools.GetLastInstanceName(methodExpression);
var methodName = tools.GetMethodName(methodExpression);
// My logic.
}
}
Now I need to create the delegates, For that I created a file and declared them without a class:
namespace Whatever
{
public delegate void VoidDelegate();
public delegate void VoidBoolDelegate(bool value);
// etc...
}
Finally, I need to maintain a class that has the same method overloaded with the different delegates.
public class FakeExtensions
{
public static void Verify(
this Fake fake,
Expression<Func<KnownType, VoidDelegate>> methodExpression)
{
var tools = new ExpressionTools();
var facilitator = new Verifier(fake, tools);
facilitator.Verify(methodExpression);
}
public static void Verify(
this Fake fake,
Expression<Func<KnownType, VoidBoolDelegate>> methodExpression)
{
var tools = new ExpressionTools();
var facilitator = new Verifier(fake, tools);
facilitator.Verify(methodExpression);
}
}
Alternative solution without delegates
The easiest solution would be to pass a default value for each parameter, but that would express that the values are also verified, which is not the case. I really dislike the idea of having something like this:
this.helper.Verify(i => i.SomeModule.SomeMethod(0, false, 0.0, null);
Since Moq is part of our testing framework, it is possible to use It.IsAny as a value for each parameter of a method call, wich expresses that the values don't matter:
this.helper.Verify(i => i.SomeModule.SomeMethod(It.IsAny<int>, It.IsAny<bool>, It.IsAny<double>, It.IsAny<SomeType>);
Why did I choose the delegates solution
I have to verify some calls on a low-level 3rd party API that has methods with up to 100 parameters. I think that the burden of maintaining a delegates list and method overloads pays off in maintainability, readability and ease of use.

Faking a generic method FakeItEasy

How would you go about faking the following:
public interface IBlah
{
Func<T, bool> ApplyFilter<T>(Func<T, bool> predicate) where T:IMessage;
}
What I would like is for the fake to simply return it's argument without any changes. However, I would like to verify that the fake has been called exactly once. A use case is given below:
public class Something
{
public Something(IBlah blah) { _blah = blah; }
public bool DoSomething(SomeValue m, Func<SomeValue, bool> predicate)
{
Func<SomeValue, bool> handler = _blah.ApplyFilter(predicate);
return handler(m);
}
}
i.e. the fake needs to act as a pass through but I also need to be able to verify it's been used.
What's the best way to go about this?
[Please don't worry about the contrived example...there's a lot of things going on under the covers, but I've simplified it down to the example above.]
Would this solve your issue? It will pass through the predicate and also verify that ApplyFilter was called exactly once
[Fact]
public void TestFeature()
{
var fake = A.Fake<IBlah>();
A.CallTo(() => fake.ApplyFilter(A<Func<int, bool>>.Ignored)).ReturnsLazily(x =>
{
return x.GetArgument<Func<int, bool>>("predicate");
});
var something = new Something(fake);
var result = something.DoSomething(1, x => x > 1);
Assert.False(result);
A.CallTo(() => fake.ApplyFilter(A<Func<int, bool>>.Ignored)).MustHaveHappened(Repeated.Exactly.Once);
}

Categories