Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit Testing with IMongoQueryable

I am using .NET Core 2.0 and the .NET Core MongoDB driver.

I have created a repository like so:

public interface IRepository<T>
{
    IMongoQueryable<T> Get()
}

I have done this to give flexibility to whoever uses this to be able to do LINQ much like they would do using EF. The problem is when it comes to unit testing and I'm trying to create an in-memory database so I can check states before and after operation.

Some stuff I tried:

public class InMemoryRepository : IRepository<ConcreteType>
{
    private HashSet<ConcreteType> _data = new HashSet<ConcreteType>();

    public IMongoQueryable<ConcreteType> Get()
    {
        return (IMongoQueryable<ConcreteType>)_data.AsQueryable();
    }
}

The case doesn't work as the interface for IMongoQueryable is:

public interface IMongoQueryable<T> : IMongoQueryable, IQueryable, IEnumerable, IQueryable<T>, IEnumerable<T>, IAsyncCursorSource<T>

Another go:

public class InMemoryRepository : IRepository<ConcreteType>
{
    private HashSet<ConcreteType> _data = new HashSet<ConcreteType>();

    public InMemoryRepository()
    {
        _mongoQueryableMock = new Mock<IMongoQueryable<ConcreteType>>();
        _mongoQueryableMock.Setup(m => m.AsQueryable()).Returns(_data.AsQueryable);
    }

    public IMongoQueryable<ConcreteType> Get()
    {
        return _mongoQueryableMock.Object;
    }
}

This doesn't work as IMongoQueryable.AsQueryable() is an extension method and I can't mock/setup that.

like image 347
Kevin Lee Avatar asked Apr 24 '26 02:04

Kevin Lee


1 Answers

Configure the mock to be able to handle IQueryable calls.

public class InMemoryRepository : IRepository<ConcreteType> {
    private HashSet<ConcreteType> _data = new HashSet<ConcreteType>();
    private Mock<IMongoQueryable<ConcreteType>> _mongoQueryableMock;

    public ReviseMeasureRepository() {    
        var queryableList = _data.AsQueryable();

        _mongoQueryableMock = new Mock<IMongoQueryable<ConcreteType>>();
        _mongoQueryableMock.As<IQueryable<ConcreteType>>().Setup(x => x.Provider).Returns(queryableList.Provider);
        _mongoQueryableMock.As<IQueryable<ConcreteType>>().Setup(x => x.Expression).Returns(queryableList.Expression);
        _mongoQueryableMock.As<IQueryable<ConcreteType>>().Setup(x => x.ElementType).Returns(queryableList.ElementType);
        _mongoQueryableMock.As<IQueryable<ConcreteType>>().Setup(x => x.GetEnumerator()).Returns(() => queryableList.GetEnumerator());    
    }

    public IMongoQueryable<ConcreteType> Get() {
        return _mongoQueryableMock.Object;
    }

    //...
}

With that out of the way I think the design of the repository is leaky and directly couples your code to external dependencies. Consider reviewing the design of the repository abstraction.

like image 66
Nkosi Avatar answered Apr 25 '26 15:04

Nkosi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!