Verify method has been called with IEnumerable containing 'x' elements with Moq - c#

I have a repository with an Add method that takes an IEnumerable as parameter:
public void Add<T>(T item) where T : class, new(){}
In a unittest I want to verify that this method is called with an IEnumerable that contains exactly the same amount of elements as another IEnumerable
[Test]
public void InvoicesAreGeneratedForAllStudents()
{
var students = StudentStub.GetStudents();
session.Setup(x => x.All<Student>()).Returns(students.AsQueryable());
service.GenerateInvoices(Payments.Jaar, DateTime.Now);
session.Verify(x => x.Add(It.Is<IEnumerable<Invoice>>(
invoices => invoices.Count() == students.Count())));
}
Result of the unit test:
Moq.MockException :
Expected invocation on the mock at least once, but was never performed:
x => x.Add<Invoice>(It.Is<IEnumerable`1>(i => i.Count<Invoice>() == 10))
No setups configured.
What am I doing wrong?

From your code example you haven't set up the x => x.Add on the Moq
session.Setup(x => x.Add(It.IsAny<IEnumerable>());
Unless the Setup for x.All is meant to be x.Add? If so, you need to match the Verify and Setup exactly - a good way to do that is to extract it to a common method that returns an Expression.
EDIT: Added a sample, I have changed the signature of Add as I can't see how you could pass a collection otherwise.
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
Mock<Boo> moqBoo = new Mock<Boo>();
moqBoo.Setup(IEnumerableHasExpectedNumberOfElements(10));
// ACT
moqBoo.Verify(IEnumerableHasExpectedNumberOfElements(10));
}
private static Expression<Action<Boo>> IEnumerableHasExpectedNumberOfElements(int expectedNumberOfElements)
{
return b => b.Add(It.Is<IEnumerable<Invoice>>(ie => ie.Count() == expectedNumberOfElements));
}
}
public class Boo
{
public void Add<T>(IEnumerable<T> item) where T : class, new()
{
}
}
public class Invoice
{
}
Also, a good way to debug these things is to set your Mock up with MockBehavior.Strict and then you'll be informed by the invoked code what you need to configure.

Related

Change behaviour of AutoFixture with AutoMoq to return false for methods

Say that I have the following interface:
public interface ITeam
{
bool HasPlayer(IPlayer player);
void AddPlayer(IPlayer player);
}
I currently have a test that looks something along the lines of (using AutoMoq):
[Theory]
[MyAutoData]
public void ShouldRosterToTeamWhenPlayerIsNotRostered(Player player, Mock<ITeam> mockedTeam)
{
player.RosterToTeam(mockedTeam.Object);
mockedTeam.Verify(team => team.AddPlayer(player), Times.Once);
}
However, a precondition in my code is that HasPlayer must return false for the test to pass when RosterToTeam is called.
This can be solved by creating a ICustomization and directly composing the correct behaviour, for example:
public class TeamCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customize<Mock<ITeam>>(composer =>
composer.Do(mock =>
mock.Setup(team => team.HasPlayer(It.IsAny<IPlayer>()))
.Returns(false)));
}
}
However, I'd like my tests always to assume that the boolean methods have a default value of false. I've tried looking into ISpecimenBuilder, but couldn't see a way to achieve this, as it seems to only work on properties, parameters, etc.
Is anyone able to recommend me a way of generically setting up all boolean methods to return false by default when created in this fashion?
Edit: The culprit behind the behaviour change is when ConfigureMembers = true is set for AutoMoqCustomization.
This is what my MyAutoDataAttribute currently looks like:
public class MyAutoDataAttribute : AutoDataAttribute
{
public MyAutoDataAttribute() : base(Create)
{
}
private static IFixture Create()
{
var fixture = new Fixture();
fixture.Customize(new AutoMoqCustomization
{
ConfigureMembers = true
});
fixture.Customize(new TeamCustomization());
return fixture;
}
}
For my use case, ConfigureMembers = true is still needed (and would like to remove the TeamCustomization).
First of all, you may want to use AutoMoqDataAttribute to create a mock of the ITeam interface:
public class AutoMoqDataAttribute : AutoDataAttribute
{
public AutoMoqDataAttribute()
: base(new Fixture().Customize(new AutoMoqCustomization()))
{
}
}
There is no need in cusomizing fixture to configure your mocks. You'd better do that in the tests itself (the arrange section):
[Theory, AutoMoqData]
public void ShouldRosterToTeamWhenPlayerIsNotRostered(Player player, Mock<ITeam> mockedTeam)
{
mockedTeam.Setup(t => t.HasPlayer(player)).Returns(false);
player.RosterToTeam(mockedTeam.Object);
mockedTeam.Verify(team => team.AddPlayer(player), Times.Once);
}
[Theory, AutoMoqData]
public void ShouldNotRosterToTeamWhenPlayerIsRostered(Player player, Mock<ITeam> mockedTeam)
{
mockedTeam.Setup(t => t.HasPlayer(player)).Returns(true);
player.RosterToTeam(mockedTeam.Object);
mockedTeam.Verify(team => team.AddPlayer(player), Times.Never);
}
and, finaly, the simplified RoastToTeam implementation:
public class Player
{
public void RosterToTeam(ITeam team)
{
if (team.HasPlayer(this))
{
return;
}
team.AddPlayer(this);
}
}
Considering everything that was proposed so far, I believe the only other option is to implement your own custom AutoMoqCustomizaiton that will treat the methods returning bool as a special case and will omit setting them.
You could create a behavior that would reset the members to return false, but you would not be able to then customize your mocks to return any value other than false, since behaviors work at the moment AutoFixture has already created the value.
Creating or altering the setup for all members returning bool in a mock object by just using reflection is not an easy task. You'll have to copy a good chunk of the AutoMoq into your code base. Luckily for you the license under which we publish AutoFixture is the most permissive of all OSS licenses, so you can copy and distribute your custom version without any restrictions.
The part that you'll likely want to change is this line here, in MockVirtualMethodsCommand. Your version should look something like this.
foreach (var method in methods.Where(x => x.ReturnType != typeof(bool)))
If this was my code-base, in cases like this I would not use mocks at all, and would probably opt for fakes. Consider the same code you proposed but instead of using Moq, the test project would implement the ITeam interface in a local class.
public class FakeTeam : ITeam
{
public List<IPlayer> Players { get; set; } = new();
public bool HasPlayer(IPlayer player)
{
return this.Players.Contains(player);
}
public void AddPlayer(IPlayer player)
{
this.Players.Add(player);
}
}
Now the same test that you wrote would look something like this.
[Theory, AutoData]
public void ShouldRosterToTeamWhenPlayerIsNotRostered(
Player player, FakeTeam team)
{
player.RosterToTeam(team);
Assert.Contains(player, team.Players);
}
Depending on your business you might even want to use the actual implementation of ITeam, and that would be fine.
As far I can see, AutoMoq resolves the returntype directly. (Source here)
Which means you can't make all method that returns bool to return false unless you inject the value (fixture.Inject(false)) - which then of course means that you'll get false each time you ask AF for a bool.
What I've done in your scenario, is to create an empty interface that inherits from the interface I want to modify the behavior for, and register it.
Like this:
...
public interface ITeamFake : ITeam {} // empty interface for modifying the mock
...
// Modify ITeam behavior
fixture.Register<Mock<ITeamFake>, Mock<ITeam>>(t =>
{
t.Setup(m => m.HasPlayer(It.IsAny<IPlayer>())).Returns(true);
return t.As<ITeam>();
});
This works for me anyways.

Can't form a Moq test to spoof context access

Completely new to Moq and mock testing in general. I'm trying to follow a tutorial but fit it to my needs, which is spoofing some database access through entityFrameworkCore contexts. How do I setup and test the response for my database returning either a 0 or an arbitrary number?
To clarify, I want to test that providing "Whatever" to my DoSomething method will return a 0 and also that providing any other string will produce an entry Id. Of course the Id is dependent on database increments in real life, so I need to just set an arbitrary number as a response and test that this is returned. This is a very minified example of my real method, of course.
I've minimised the setup as much as possible:
Interface:
public interface ITestClass
{
int DoSomething(string thing);
}
Implementation:
public class TestClass : ITestClass
{
private readonly TestContext _testContext;
public TestClass(TestContext testContext)
{
_testContext = testContext;
}
public int DoSomething(string thing)
{
if (thing == "Whatever") return 0;
Item i = new Item()
{
Thing = thing
};
_testContext.Add(i);
_testContext.SaveChanges();
return i.Id;
}
}
Context:
public class TestContext : DbContext
{
public TestContext(DbContextOptions<TestContext> options) : base(options) { }
}
Table / model class:
public class Item
{
public int Id { get; set; }
public string Thing { get; set; }
}
I've ignored connection strings because the whole point is to test the method without connecting to a database, right? And finally here's my attempt at mocking which I'm completely clueless about, tbh:
public void Test1()
{
var mock = new Mock<ITestClass>();
mock.Setup(m => m.DoSomething("Whatever"));
// Assert returns 0
mock.Setup(m => m.DoSomething("ValidString"));
// Assert returns arbitrary 12345 - where do I spoof this number?
}
I think you have a fundamental misunderstanding of how mocking is used. Lets look at your test
public void Test1()
{
var mock = new Mock<ITestClass>();
mock.Setup(m => m.DoSomething("Whatever"));
// Assert returns 0
mock.Setup(m => m.DoSomething("ValidString"));
// Assert returns arbitrary 12345 - where do I spoof this number?
}
Now when you use Setup on a mock, you are also to use Returns, ReturnsAsync, or Throws to tell the mock what you want it to return when you provide these values. So your setup for DoSomething should look like this
mock.Setup(m => m.DoSomething(It.Is<string>(i => i == "ValidString"))).Returns(12345);
But there should be an obvious problem here. If we are explicitly telling it exactly what to give us for a given input, then what are we really testing? Just the mock itself at that point. This isn't how mocks are intended to be used. So a rule, never mock the thing you are testing. Instead you mock its dependencies. In this case, the only one is the TestContext. Instead, we actually want to test the DoSomething method, so we create a real instance of that class to test.
You didn't specify which testing framework you are using, so I wrote mine with NUnit
[Test]
public void Test1()
{
// Mock the dependency
Mock<ITestContext> mockContext = new Mock<ITestContext>();
mockContext.Setup(m => m.Add(It.IsAny<Item>()))
.Returns(true);
mockContext.Setup(m => m.SaveChanges())
.Returns(true);
// Inject the dependency
TestClass testClass = new TestClass(mockContext.Object);
int result = testClass.DoSomething("Whatever");
// Verify the methods on the mock were called once
mockContext.Verify(m => m.Add(It.IsAny<Item>()), Times.Once);
mockContext.Verify(m => m.SaveChanges(), Times.Once);
// Assert that the result of the operation is the expected result defined elsewhere
Assert.That(result, Is.EqualTo(ExpectedResult));
}
Testing that a mock returns what you set it up to return offers no value. We want to test the real deal, mocking just makes that possible when the dependencies are complex. They are a stand-in the for backend systems and complex object graphs that the real system uses in practice and nothing more. The magic is that it allows us to only set up the parts of the mock that we need, the specific function calls and property access that the class which is dependent on it relies, without having to worry about setting up the entire class and all of its dependencies and so on.

How to fake an action<> with FakeItEasy

I'm working with the FakeItEasy library to create fakes for my unit tests.
I have a ClassUnderTest on which I want to test the method MethodToTest(Data dataObject). This method is calling a method of an interface which I want to fake:
public interface IFoo
{
void Execute(Action<IDataAccess> action);
}
public class ClassUnderTest
{
private IFoo _foo;
public ClassUnderTest(IFoo foo)
{
_foo = foo;
}
public void MethodToTest(Data dataObject)
{
_foo.Execute(dataAccess => dataAccess.Update(dataObject));
}
}
public interface IDataAccess
{
void Update(Data data);
}
public class Data
{
public int Property { get; set; }
}
In my unit tests I want to check if the test method calls the interface correctly (with the correct property value):
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
var foo = A.Fake<IFoo>(x => x.Strict());
A.CallTo(() => foo.Execute(dataAccess => dataAccess.Update(A<Data>.That.Matches(d => d.Property == 20))));
var cut = new ClassUnderTest(foo);
cut.MethodToTest(new Data { Property = 20 });
}
}
But something is configured wrong in this test. I get the exception:
Test method TestProject1.UnitTest1.TestMethod1 threw exception:
FakeItEasy.ExpectationException: Call to non configured method "Execute" of strict fake.
Does somebody have an idea of how I have to configure the CallTo() statement correctly?
The updated example really helps, #rhe1980.
First some notes about the test you supplied:
the A.CallTo method doesn't do anything - it's not setting up behaviour (with a .Invokes or a .Returns or even a .DoesNothing) or verifying that the method has been called (for example with .MustHaveHappened).
Comparing Actions appears to be tough. I did find some advice over at Compare Delegates Action<T>, but if it were me, I'd take a slightly different tack.
Instead of attempting to compare the Action delegate to a reference model, I figured I could emulate this by capturing the action supplied to Execute and then running it on an IDataAccess and see what the action does. Fortunately, we have FakeItEasy to help with that!
I had success with this test:
[TestMethod]
public void TestMethod1()
{
// Arrange
var foo = A.Fake<IFoo>(x => x.Strict());
var fakeDataAccess = A.Fake<IDataAccess>();
A.CallTo(() => foo.Execute(A<Action<IDataAccess>>.Ignored))
.Invokes((Action<IDataAccess> action)=>action(fakeDataAccess));
var cut = new ClassUnderTest(foo);
// Act
cut.MethodToTest(new Data { Property = 20 });
// Assert
A.CallTo(() => fakeDataAccess.Update(A<Data>.That.Matches(d => d.Property == 20)))
.MustHaveHappened();
}
I hope it helps.
If I understood your intentions correctly, you need to use something as follows:
A.CallTo(() => foo.Execute(A<Action<IDataAccess>>.Ignored).MustHaveHappened();

Verifying generic method called using Moq

I'm having trouble verifying that mock of IInterface.SomeMethod<T>(T arg) was called using Moq.Mock.Verify.
I'm can verify that method was called on a "Standard" interface either using It.IsAny<IGenericInterface>() or It.IsAny<ConcreteImplementationOfIGenericInterface>(), and I have no troubles verifying a generic method call using It.IsAny<ConcreteImplementationOfIGenericInterface>(), but I can't verify a generic method was called using It.IsAny<IGenericInterface>() - it always says that the method was not called and the unit test fails.
Here is my unit test:
public void TestMethod1()
{
var mockInterface = new Mock<IServiceInterface>();
var classUnderTest = new ClassUnderTest(mockInterface.Object);
classUnderTest.Run();
// next three lines are fine and pass the unit tests
mockInterface.Verify(serviceInterface => serviceInterface.NotGenericMethod(It.IsAny<ConcreteSpecificCommand>()), Times.Once());
mockInterface.Verify(serviceInterface => serviceInterface.NotGenericMethod(It.IsAny<ISpecificCommand>()), Times.Once());
mockInterface.Verify(serviceInterface => serviceInterface.GenericMethod(It.IsAny<ConcreteSpecificCommand>()), Times.Once());
// this line breaks: "Expected invocation on the mock once, but was 0 times"
mockInterface.Verify(serviceInterface => serviceInterface.GenericMethod(It.IsAny<ISpecificCommand>()), Times.Once());
}
Here is my class under test:
public class ClassUnderTest
{
private IServiceInterface _service;
public ClassUnderTest(IServiceInterface service)
{
_service = service;
}
public void Run()
{
var command = new ConcreteSpecificCommand();
_service.GenericMethod(command);
_service.NotGenericMethod(command);
}
}
Here is my IServiceInterface:
public interface IServiceInterface
{
void NotGenericMethod(ISpecificCommand command);
void GenericMethod<T>(T command);
}
And here is my interface/class inheritance hierarchy:
public interface ISpecificCommand
{
}
public class ConcreteSpecificCommand : ISpecificCommand
{
}
It is a known issue in the Moq 4.0.10827 which is a current release version. See this discussion at GitHub https://github.com/Moq/moq4/pull/25. I have downloaded its dev branch, compiled and referenced it and now your test passes.
I'm going to wing it. Since GenericMethod<T> requires that a T argument be provided, would it be possible to do:
mockInterface.Verify(serviceInterface => serviceInterface.GenericMethod(It.Is<object>(x=> typeof(ISpecificCommand).IsAssignableFrom(x.GetType()))), Times.Once());

Reset ObjectFactory in StructureMap

I'm writing some unit tests that rely on StructureMap so I want to completely reset the ObjectFactory in my [SetUp] method. This is what my [SetUp] method looks like right now:
[SetUp]
public void SetUp()
{
ObjectFactory.Initialize(initializationExpression => {});
}
This appears to reset the configuration because I can execute the ObjectFactory.WhatDoIHave() method and it does not contain any of my configuration. However, cached instances of objects are not removed and are returned in subsequent tests. Is there a way to completely reset the ObjectFactory?
I thought I might have to use ObjectFactory.EjectAllInstancesOf(), but that doesn't appear to help.
I'm using version 2.5.3.
Here is some contrived code to show what I'm talking about. I would expect this test to pass, but it doesn't.
[TestFixture]
public class TestingStructureMap
{
[Test]
public void FirstTestUsingCachedObjects()
{
ObjectFactory.Configure(configure =>
configure.ForRequestedType<ISomeInterface>()
.TheDefaultIsConcreteType<SomeImplementation>()
.CacheBy(InstanceScope.ThreadLocal)
);
ISomeInterface firstSomeInterface = ObjectFactory.GetInstance<ISomeInterface>();
Assert.AreEqual(1, firstSomeInterface.ID);
ObjectFactory.Initialize(initializationExpression => { });
ObjectFactory.EjectAllInstancesOf<ISomeInterface>();
ObjectFactory.Configure(configure =>
configure.ForRequestedType<ISomeInterface>()
.TheDefaultIsConcreteType<SomeImplementation>()
.CacheBy(InstanceScope.ThreadLocal)
);
ISomeInterface secondSomeInterface = ObjectFactory.GetInstance<ISomeInterface>();
Assert.AreEqual(2, secondSomeInterface.ID);
}
public interface ISomeInterface
{
int ID { get; }
}
public class SomeImplementation : ISomeInterface
{
private static int NumberOfInstancesCreated;
private readonly int id;
public int ID
{
get { return id; }
}
public SomeImplementation()
{
id = ++NumberOfInstancesCreated;
}
}
}
Not exactly an answer but to have you considered wrinting your test such that you do not rely on the ObjectFactory but the StructureMap container?
var c = new StructureMap.Container(ce=>
{
ce.ForRequestedType<IFoo>().TheDefaultIsConcreteType<Bar>();
});
In that case you can simply recreate the container and my guess is that it should be in pristine condition.
I've figured it out. ObjectFactory.EjectAllInstancesOf() is actually dependant on there being a configuration for T. In my code, I nullified the effectiveness of ObjectFactory.EjectAllInstancesOf() by first clearing all of the configuration. If I switch these two lines of code, it works.
This does NOT work:
ObjectFactory.Initialize(initializationExpression => { });
ObjectFactory.EjectAllInstancesOf<ISomeInterface>();
This DOES work:
ObjectFactory.EjectAllInstancesOf<ISomeInterface>();
ObjectFactory.Initialize(initializationExpression => { });

Categories