Verify method called with list of parameters, one time each? - c#

I have a test where I have a set of parameters, and I'd like to verify that the method was called and each parameter was specified exactly once. I can do this:
var paramList = new List<string> { "one", "two", "three", "four" };
paramList.ForEach(x => MyMock.Verify(y => y.DoSomething(x), Times.Once));
But I'm wondering if Moq offers something I can do with just a single Verify call.

I don't think moq offers that if I am not mistaken. The problem is that even if you have proper setup with Verifiable to use Verify or if you want to use VerifyAll you cannot specify Times limitation.
Verify
paramList.ForEach(s => mock.Setup(m => m.DoSomething(s)).Verifiable());
mock.Object.DoSomething("one");
mock.Object.DoSomething("two");
mock.Object.DoSomething("three");
mock.Object.DoSomething("four");
mock.Verify(); //Cannot specify Times
VerifyAll
paramList.ForEach(s => mock.Setup(m => m.DoSomething(s)));
mock.Object.DoSomething("one");
mock.Object.DoSomething("two");
mock.Object.DoSomething("three");
mock.Object.DoSomething("four");
mock.VerifyAll(); //Cannot specify Times
Although, I do not see any problem with your approach I just want to add one more option. You could avoid Verify by using Capture.In feature, something like this:
//Arrange
var invocation = new List<string>();
mock.Setup(m => m.DoSomething(Capture.In(invocation)));
//Act
mock.Object.DoSomething("one");
mock.Object.DoSomething("two");
mock.Object.DoSomething("three");
mock.Object.DoSomething("four");
//Assert
CollectionAssert.AreEquivalent(paramList, invocation);

Related

Moq setups overlapping. What will be if setup any case and concrete after it?

I want to setup the return value for the call with any arguments except one specified case, and another return value for this one case. Does the following code provide expected behavior? Does the test pass? And is it guaranteed for other possible situation that follows the described structure?
interface ISomeInterface
{
int SomeMethod(string param);
}
[TestMethod]
public void SomeClass_ShouldBehaveProperly_GivenSomeScenario()
{
var mock = new Mock<ISomeInterface>(MockBehavior.Strict);
mock.Setup(m => m.SomeMethod(It.IsAny<string>()))
.Returns(1);
mock.Setup(m => m.SomeMethod("aSpecificString"))
.Returns(100);
Assert.AreEquel(100, mock.Object.SomeMethod("aSpecificString"));
Assert.AreEquel(1, mock.Object.SomeMethod("anyString"));
}
And how about mixed setups, for example when we setup 'throws exception' for any argument, but 'returns value' for some specified?
mock.Setup(m => m.SomeMethod(It.IsAny<string>()))
.Throws<Exception>();
mock.Setup(m => m.SomeMethod("aSpecificString"))
.Returns(100);
What behavior is expected from the setup provided in the last code example?
From the accepted answer to this question I know that
The last call wins and nullifies previous calls
But, do we have the same behavior when setups are in reverse order?
But, do we have the same behavior when setups are in reverse order?
No (Not in this case)
After testing it, it appears that when more specific expectations are done after the more loose matches the behavior is as expected
For example
[TestMethod]
public void SomeClass_ShouldBehaveProperly_GivenSomeScenario() {
var mock = new Mock<ISomeInterface>(); // Works for Strict or Loose
mock.Setup(m => m.SomeMethod(It.IsAny<string>()))
.Throws<InvalidOperationException>();
mock.Setup(m => m.SomeMethod("aSpecificString"))
.Returns(100);
mock.Setup(m => m.SomeMethod("anotherString"))
.Returns(1);
Assert.AreEqual(100, mock.Object.SomeMethod("aSpecificString")); //PASS
Assert.AreEqual(1, mock.Object.SomeMethod("anotherString")); //PASS
Assert.ThrowsException<InvalidOperationException>(() =>
mock.Object.SomeMethod("anyString")); //PASS
}
If however, the same expectations are done multiple times, the last one wins
For example
[TestMethod]
public void SomeClass_ShouldBehaveProperly_GivenSomeScenario2() {
var mock = new Mock<ISomeInterface>();
mock.Setup(m => m.SomeMethod(It.IsAny<string>()))
.Throws<InvalidOperationException>();
mock.Setup(m => m.SomeMethod("aSpecificString"))
.Returns(100);
mock.Setup(m => m.SomeMethod("aSpecificString"))
.Returns(1);
Assert.ThrowsException<InvalidOperationException>(() =>
mock.Object.SomeMethod("anyString")); //PASS
Assert.AreEqual(100, mock.Object.SomeMethod("aSpecificString")); //Fail
}

Moq setup treats all empty enumerables/arrays as the same parameter

I have a method that accepts an IEnumerable:
MyMethod(IEnumerable<MyClass> myParameter)
Now I am writing this code to mock the service:
var array1 = new MyClass[0];
var array2 = new MyClass[0];
_service
.Setup(s => s.MyMethod(array1))
.Returns(value1);
_service
.Setup(s => s.MyMethod(array2))
.Returns(value2);
And finally I am doing two calls to the service with both arrays inside system under test:
_service.MyMethod(array1);
_service.MyMethod(array2);
What I do expect is to get value1 and value2 from these calls, but in practice the latter call overrides the first one and I only get value2 from both calls.
Is this a bug in Moq or is this a feature that setup treats IEnumerable not as a separate object but rather tries to expand it and compare all elements or something (resulting in two empty arrays being the same setup call)?
When you create multiple setups on a method with Moq, each subsequent setup will replace the previous setup unless the setups are conditional (they specify certain conditions on the arguments). See this answer.
You can fix your code by specifying that the arguments must match the ones you intend to pass:
[Test]
public void MyTest()
{
var service = new Mock<MyClass>();
var array1 = new MyClass[0];
var array2 = new MyClass[0];
var value1 = "value1";
var value2 = "value2";
service.Setup(s => s.MyMethod(It.Is<IEnumerable<MyClass>>(e => e == array1))).Returns(value1);
service.Setup(s => s.MyMethod(It.Is<IEnumerable<MyClass>>(e => e == array2))).Returns(value2);
Assert.AreEqual(value1, service.Object.MyMethod(array1));
Assert.AreEqual(value2, service.Object.MyMethod(array2));
}
The behaviour you describe is the default behaviour of the moq, you can see it here. It indeed unfold enumerable and invoke IEnumerable.SequenceEqual. However that is default behaviour(if you setup using an instance, Constant matcher) and you could override it. The one approach is what Owen suggested to use It.Is<T> matcher, e.g.
service.Setup(s => s.MyMethod(It.Is<IEnumerable<MyClass>>(e => e == array1)))
service.Setup(s => s.MyMethod(It.Is<IEnumerable<MyClass>>(e => e == array2)))
Notice that == by default do ReferenceEquals() so this will make different non overridable setups.

Rhino Mocks, assert that a MockRepository was not used (methods)?

Is there a way of asserting that no methods were called in MockRepository?
Say I have:
var repo = MockRepository.GenerateStub<RealRepo>();
I know I can do:
repo.AssertWasNotCalled(...);
But is there a way of checking that it was not used? Instead of doing all the methods everytime i want to check if a repo was not used?
I have cases where I want to just check that I don't use this repo.
Use StrictMock instead of stub:
var repo = MockRepository.GenerateStrictMock<RealRepo>();
It will throw exception if you will try to call any member which do not have setup.
BTW same is true for Moq:
var repoMock = new Mock<RealRepo>(MockBehavior.Strict);
You can try adding your own extension to Rhino Mocks. Something like this:
public static void AssertNothingWasCalled<T>(this T mock)
{
var methodsToVerify = typeof (T)
.GetMethods()
.Where(m => !m.IsSpecialName);
foreach (var method in methodsToVerify)
{
var arguments = BuildArguments(method);
var action = new Action<T>(x => method.Invoke(x, arguments));
mock.AssertWasNotCalled(action, y => y.IgnoreArguments());
}
}
private static object[] BuildArguments(MethodInfo methodInfo)
{
return methodInfo
.GetParameters()
.Select(p => Arg<object>.Is.Anything)
.ToArray();
}
But the answer by Sergey Berezovskiy seems a bit simpler.
Perhaps the easiest thing to do would be to pass a null ref to the calling class. Your SUT should throw a NullReferenceException if it attempts to use it. This is possibly the simplest thing that will work.
However, if the SUT checks for null, then this won't work.

Use of rhino mocks to return specific results based on a provided Expression

I use a generic repository to access data in C#, the method signature of which is this:
public virtual IEnumerable<TEntity> Get(
Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "")
this is then used in an MVC controller (for example) in the following ways
var users = UnitOfWork.UserRepository.Get(
u => u.Id == userId, null, "CreatedEmployer,CreatedEmployer.CreatedByUser");
var checkUser = UnitOfWork.UserRepository.Get(u => u.UserName == email)
.FirstOrDefault();
I want to be able to mock these calls using RhinoMocks and receive specific results based on the expression that was called. The pseudo code below demonstrates what I want to achieve e.g.
UnitOfWork.UserRepository.Expect(
u => u.Get(Arg<Expression<Func<User, bool>>>.Matches(u.UserName == "jim")))
.Return(new List<User>() { userJim });
UnitOfWork.UserRepository.Expect(
u => u.Get(Arg<Expression<Func<User, bool>>>.Matches(u.UserName == "jo left ages ago")))
.Return(new List<User>() );
I have tried using .WhenCalled but it does not seem to have the behaviour I want which is when matching a provided an exact provided expression, return some specific data:
.WhenCalled(invocation => {
var predicate = invocation.Arguments.First() as Expression<Func<User, bool>>;
... Do something here
})
I've been trawling the internet for a while on this but have not managed to dig up a decent solution, most of the solutions consist of ignoring the arguments which works so long as you only call the repo once in a method e.g.
UserRepository.Expect(u => u.Get()).IgnoreArguments()
.Return(new List<User> { CurrentUser });
This has now proved inadequate and I need something a bit more robust and specific. I am only really interested in the first argument. I need a solution to the above but if a solution does not exist for RhinoMocks then I'd be interested in any mocking framework where testing expressions was easier to achieve.
I have answered similar question using Moq. You can use the same approach with Rhino.
The key is to use a real (or mocked) data set, and run the expressions against it.
Here is an adaptation of the solution proposed by Sunny. Thanks for his advice and the steer to the solution for RhinoMocks.
For all tests you have an object called which is all the data that might ever be returned from any of your calls to the repository. In my case this is the users data set:
List<User> users = new List<User>();
Then at each arrange you add new users
users.Add(new User() { username="jim" });
users.Add(new User() { username="jo left ages ago" });
Then you call once to Expect. This sets up any call to the repo to query the data you have provided. For some reason this does not work with two calls to expect. To Rhino Mocks it only appears as if one call has been made:
baseController.UnitOfWork.UserRepository.Expect(u => u.Get(Arg<Expression<Func<User, bool>>>.Is.Anything, Arg<Func<IQueryable<User>, IOrderedQueryable<User>>>.Is.Anything, Arg<string>.Is.Anything))
.WhenCalled(invocation =>
{
var predicate = invocation.Arguments.First() as Expression<Func<User, bool>>;
var query = predicate.Compile();
invocation.ReturnValue = users.Where(query);
});
As an aside, it still doesn't fit nicely with the way calls to SpecFlow's Given statements setup the expectations. What natural statement do you associate with setting up the Expect? But it does answer my original question.

Is .Callback the right way to mock a void-returning method using Moq?

I would like to unit test an Add method in a repository that returns void. I'm interested in testing the actual adding of elements without hitting the database (not whether Add was called or not). Is this the correct way?
var list = new List<Foo>();
var repo = new Mock<IFooRepository>();
repo.Setup(x => x.Add(It.IsAny<Foo>()))
.Callback((Foo f) =>
{
list.Add(f);
});
repo.Object.Add(new Foo { FooId = 1 });
Assert.IsTrue(list.Any(x => x.FooId == 1));
No, the only thing you're testing here is Moq itself. You could try mocking the underlying layer, e.g. ISession if you're using Nhibernate.

Categories