Это, по моему мнению, является утечкой абстракции как часть проблемы XY .
Из комментариев
Независимо от того, как вы абстрагируете некоторыечасть вашего кода будет обрабатывать MongoCollection, как вы тестируете этот класс?
Я бы не стал тестировать этот класс.Класс, который в конечном итоге обернет коллекцию, не нужно будет подвергать модульному тестированию, поскольку он будет просто оберткой для сторонней организации.Разработчики MongoCollection протестировали бы их код для выпуска.Я вижу всю зависимость монго как стороннюю реализацию реализации.
Взгляните на следующий альтернативный дизайн
public interface ICarRepository {
IEnumerable<CarDocument> GetCars(Expression<Func<CarDocument, bool>> filter = null);
}
public class CarRepository : ICarRepository {
private readonly IMongoDatabase database;
public CarRepository(Options options) {
var client = new MongoClient(options.ConnectionString);
database = client.GetDatabase(options.DatabaseName");
}
public IEnumerable<CarDocument> GetCars(Expression<Func<CarDocument, bool>> filter = null) {
IMongoCollection<CarDocument> cars = database.GetCollection<CarDocument>(options.CollectionName);
return filter == null ? cars.AsQueryable() : (IEnumerable<CarDocument>)cars.Find(filter).ToList();
}
}
Для простоты я переименовал некоторые из зависимостей.Это должно быть само за себя.Все проблемы, связанные с Монго, заключены в его собственном беспокойстве.Хранилище может использовать всю мощь клиента MongoDb по мере необходимости без утечки ненужных зависимостей от сторонних задач.
Зависимый класс запросов может быть соответственно реорганизован
public class GetCarQuery {
private readonly ICarRepository repository;
public GetCarQuery(ICarRepository repository) {
this.repository = repository;
}
public CarDocument Query(string aKey) {
var match = repository.GetCars(x => x.AKey == aKey);
return match.Any()
? match.First()
: repository.GetCars(x => x.AKey == "Default").FirstOrDefault();
}
}
Удачный путь длявышеприведенный класс теперь можно просто смоделировать в изолированном модульном тесте
public class GetCarQueryTest {
[Test]
public void ShouldGetByApiKey() {
//Arrange
var aKey = "a-key";
var mockCarDocument = new CarDocument() {
AKey = aKey
};
var data = new List<CarDocument>() { mockCarDocument };
var repository = new Mock<ICarRepository>();
repository.Setup(_ => _.GetCars(It.IsAny<Expression<Func<CarDocument, bool>>>()))
.Returns((Expression<Func<CarDocument, bool>> filter) => {
return filter == null ? data : data.Where(filter.Compile());
});
var getCarQuery = new GetCarQuery(repository.Object);
//Act
var car = getCarQuery.Query(aKey);
//Assert
car.Should().Be(mockCarDocument);
}
}
Для проверки реальных проблем, связанных с Mongo, потребуется интеграционный тест, в котором вы будете подключаться к фактическому источнику для обеспечения ожидаемого поведения.