1

In my unit test I want to test my method that I created for filtering data from MongoDB.

When I try to mock my function like this:

_repo.GetFluent<Location>((Arg.Any<Expression<Func<Location, bool>>>()))
                .Returns(x => locations.Where(x.Arg<Expression<Func<Location, bool>>>()).ToList());

It underlines the Returns saying:

Cannot convert lambda expression.

Before when I worked on my simple project using the 2.0.0 MongoDB driver I had no problem mocking my Get() function like this, but now with the new 2.2.3 driver I have an error mocking this. Is there another way?

I've seen that the new driver is using IFindFluent and the older one I used the MongoCursor to get my data.

Should I mock the IFindFluent somehow?

This is my code for the GetFluent() method

public IFindFluent<TEntity, TEntity> GetFluent<TEntity>(System.Linq.Expressions.Expression<Func<TEntity, bool>> filter = null) where TEntity : class, new()
        {
            var collection = GetCollection<TEntity>();
            if (filter == null)
            {
                var emptyFilter = Builders<TEntity>.Filter.Empty;
                return collection.Find(emptyFilter);
            }
            else
            {
                var filterDefinition = Builders<TEntity>.Filter.Where(filter);
                return collection.Find(filterDefinition);
            }
        }

2 Answers2

0

Yes, you need to mock IFindFluent. Let me show you an example.

I used NUnit and Moq for tests, driver version is 2.2.3.

public interface IRepository
{
    IFindFluent<TEntity, TEntity> GetFluent<TEntity>(Expression<Func<TEntity, bool>> filter = null)
        where TEntity : class, new();
}

public class LocationService
{
    public long CountLocations(IRepository repository)
    {
        return repository.GetFluent<Location>(location => true).Count();
    }
}

[TestFixture]
public class LocationServiceTests
{
    [Test]
    public void CountLocationsTest()
    {
        const long LocationCount = 5;

        var locationsMock = new Mock<IFindFluent<Location, Location>>();
        locationsMock.Setup(x => x.Count(default(CancellationToken))).Returns(LocationCount);

        var repoMock = new Mock<IRepository>();
        repoMock.Setup(repo => repo.GetFluent(It.IsAny<Expression<Func<Location, bool>>>()))
                .Returns(locationsMock.Object);

        var locationService = new LocationService();
        long result = locationService.CountLocations(repoMock.Object);

        Assert.AreEqual(LocationCount, result);
    }
}
Usein Mambediiev
  • 243
  • 2
  • 11
0

Good answer from Usein Mambediev. There is an similar example, how to mock IFindFluent with Typemock Isolator without wrapping it into the interface:

 [TestMethod, Isolated]
 public void TestGet()
 {
     var target = new ClassUnderTest();
     var returnMock = Isolate.Fake.Instance<IFindFluent<Location, Location>>();

     int size = 3;

     Isolate.WhenCalled(() => returnMock.Count()).WillReturn(size);
     Isolate.WhenCalled(() => target.GetFluent(default(Expression<Func<Location, bool>>))).WillReturn(returnMock);

     Assert.AreEqual(size, target.GetFluent<Location>(location => true).Count());
}

I've put your method into the public class just in order to test. You only need to change the target. Good luck!

JamesR
  • 745
  • 4
  • 15