如何使用 Moq 模拟 IMongoCollection.Find

Yah*_*ein 7 c# unit-testing moq mongodb .net-core

我正在努力IMongoCollection.Find使用 Moq 进行单元测试的模拟方法。

我试过的:

  Mock<IMongoCollection<Person>> mockIMongoCollection = new Mock<IMongoCollection<Person>>();
  mockIMongoCollection.SetupAllProperties();
  mockIMongoCollection
            .Setup(x => x.Find(
                It.IsAny<FilterDefinition<Person>>(),
                It.IsAny<FindOptions>()))
            .Returns();
Run Code Online (Sandbox Code Playgroud)

事情是我尝试使用返回的任何内容Returns(),它不起作用,我希望能够返回可转换为的内容,List<Person>并且我无法模拟或创建方法IFindFluent<Person,Person>返回类型所建议的实例Find

Pab*_*ona 7

我知道这个问题有点老了,但是最近在开发单元测试模拟 mongo 驱动程序时遇到了同样的问题,并且我没有找到模拟此方法的具体方法。所以这是我的解决方案:

如前所述,它是一个无法模拟的静态方法,您应该模拟内部将调用的非静态方法。

Find 方法将创建并返回 FindFluent 的实例,该实例实现了 IFindFluent 接口(并扩展了 IAsyncCursorSource 接口),该接口将使用非静态集合方法以及该接口的静态扩展方法。

所以你应该找到并分析find后你将使用的方法,以及它使用的mock组件。例如,要将结果加载到列表中:

public List<Person> LoadPeople(IMongoCollection<Person> collection)
{
  return collection.find(Builders<Person>.Filter.Empty).ToList();
}
Run Code Online (Sandbox Code Playgroud)

测试它:

[Fact]
public void LoadPeopleTest()
{
  var mockIMongoCollection = new Mock<IMongoCollection<Person>>();
  var asyncCursor = new Mock<IAsyncCursor<Person>>();

  var expectedResult = fixture.CreateMany<Person>(5);
  
  mockIMongoCollection.Setup(_collection => _collection.FindSync(
      Builders<Person>.Filter.Empty,
      It.IsAny<FindOptions<Person>>(),
      default))
    .Returns(asyncCursor.Object);

  asyncCursor.SetupSequence(_async => _async.MoveNext(default)).Returns(true).Returns(false);
  asyncCursor.SetupGet(_async => _async.Current).Returns(expectedResult);

  var result = LoadPeople(mockIMongoCollection.Object);
  
  Assert.Equals(expectedResult, result);
}
Run Code Online (Sandbox Code Playgroud)

涉及班级:

https://github.com/mongodb/mongo-csharp-driver/blob/master/src/MongoDB.Driver/IMongoCollectionExtensions.cs

https://github.com/mongodb/mongo-csharp-driver/blob/master/src/MongoDB.Driver/FindFluent.cs

https://github.com/mongodb/mongo-csharp-driver/blob/master/src/MongoDB.Driver.Core/IAsyncCursorSource.cs

  • 你的例子中的fixture是什么?我也没有在您的任何链接文件中看到它的定义。谢谢 (2认同)

Mac*_*jek 5

也许这会帮助你。

我不得不模拟这样的查询:

 var queryRecords = await queryCollection
                .Find(filters)
                .Project(projection)
                .Skip(queryCriteria.Skip)
                .Limit(queryCriteria.Limit)
                .Sort(sort);
Run Code Online (Sandbox Code Playgroud)

为此,我为 MongoCollection 创建了一个抽象来处理 mongo 查询。

public interface IFakeMongoCollection : IMongoCollection<BsonDocument>
{
    IFindFluent<BsonDocument, BsonDocument> Find(FilterDefinition<BsonDocument> filter, FindOptions options);

    IFindFluent<BsonDocument, BsonDocument> Project(ProjectionDefinition<BsonDocument, BsonDocument> projection);

    IFindFluent<BsonDocument, BsonDocument> Skip(int skip);

    IFindFluent<BsonDocument, BsonDocument> Limit(int limit);

    IFindFluent<BsonDocument, BsonDocument> Sort(SortDefinition<BsonDocument> sort);
}
Run Code Online (Sandbox Code Playgroud)

所以我的测试设置看起来像这样

[TestFixture]
class QueryControllerTests
{
    private IOptions<MongoSettings> _mongoSettings;
    private QueryController _queryController;
    private Mock<IFakeMongoCollection > _fakeMongoCollection;
    private Mock<IMongoDatabase> _fakeMongoDatabase;
    private Mock<IMongoContext> _fakeMongoContext;
    private Mock<IFindFluent<BsonDocument, BsonDocument>> _fakeCollectionResult;

    [OneTimeSetUp]
    public void Setup()
    {
        _fakeMongoCollection = new Mock<IFakeMongoCollection >();
        _fakeCollectionResult = new Mock<IFindFluent<BsonDocument, BsonDocument>>(
        _fakeMongoDatabase = new Mock<IMongoDatabase>();
        _fakeMongoDatabase
            .Setup(_ => _.GetCollection<BsonDocument>("Test", It.IsAny<MongoCollectionSettings>()))
            .Returns(_fakeMongoCollection.Object);

        _fakeMongoContext = new Mock<IMongoContext>();
        _fakeMongoContext.Setup(_ => _.GetConnection()).Returns(_fakeMongoDatabase.Object);        
        var configuration = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json", false)
            .Build();
        _mongoSettings = Options.Create(configuration.GetSection("MongoConnection").Get<MongoSettings>());
        _queryController = new QueryController(_mongoSettings, _fakeMongoContext.Object);
    }
}
Run Code Online (Sandbox Code Playgroud)

我希望它有帮助。

  • 如果我错了,请纠正我,但例如 Find 方法不能从此被嘲笑。它仍然是IMongoCollection中的一个扩展方法。对我来说,我得到`System.NotSupportedException:不支持的表达式:_collection =&gt; _collection.Find&lt;Product&gt;(mockClientSession.Object, It.IsAny&lt;FilterDefinition&lt;Product&gt;&gt;(), null) 扩展方法(此处:IMongoCollectionExtensions.Find)不得在设置/验证表达式中使用。` (2认同)