如何模拟两个具有不同结果的相同 mongo 集合?

How to mock two same mongo collection with different results?

我必须模拟指向同一个集合的两个聚合管道方法。

下面的示例代码

private void GetMethod()
{

  var result1 = databaseContext.GetCollection<SampleCollection>("SampleCollection")
           .Aggregate<SampleModel>(aggregateQuery, new AggregateOptions { AllowDiskUse = true }).ToList();
          

  var result2 = databaseContext.GetCollection<SampleCollection>("SampleCollection")
           .Aggregate<SampleModel>(aggregateQuery, new AggregateOptions { AllowDiskUse = true }).ToList();
          
}

下面是我尝试模拟集合的代码。

 List<SampleModel> models = new List<SampleModel>
            {
                new SampleModel
                {
                   Quarter = 20141,
                   Type = "AA",
                   PaidAmount = 100                    
                },
                  new SampleModel
                {
                   Quarter = 20141,
                   Type = "BB",
                   PaidAmount = 200                    
                }
            }; 
            
            var mockMongoCollection = new Mock<IMongoCollection<SampleCollection>>();            
            var mockCursor = new Mock<IAsyncCursor<SampleModel>>();
            mockCursor.Setup(x => x.Current).Returns(models);
            mockCursor.SetupSequence(x => x.MoveNext(It.IsAny<CancellationToken>())).Returns(true).Returns(false);
            mockMongoCollection.SetupSequence(x => x.Aggregate(It.IsAny<PipelineDefinition<SampleCollection, SampleModel>>(), It.IsAny<AggregateOptions>(), It.IsAny<CancellationToken>()))
                .Returns(mockCursor.Object);          
            this.mockDbContext.Setup(x => x.GetCollection<SampleCollection>(It.IsAny<string>()))
            .Returns(mockMongoCollection.Object);

如何为每个聚合模拟和设置不同的结果? .我试过的模拟代码只适用于第一个聚合查询。

这里的关键是唯一标识两个管道的两次调用。

如果您确定测试中的哪个管道调用将首先执行,您可以使用 SetupSequence 来控制 return 值。您已经在 MoveNext 方法模拟设置中使用过。两者的管道定义看起来如何都无关紧要。

如果不是这种情况,那么您需要编写条件来唯一标识调用。

例如:

mockMongoCollection.SetupSequence(c =>
    c.Aggregate(
        It.Is<PipelineDefinition<SampleCollection, SampleModel>>(x => x.Stages.Count() == 2),
        It.IsAny<AggregateOptions>(),
        It.IsAny<CancellationToken>()))
.Returns(mockCursor.Object);   

上面的例子只是简单的演示了根据pipeline中定义了多少stage来进行识别。假设第一个管道有 2 个阶段,第二个管道有 3 个阶段,那么您可以使用它来设置您的模拟。

您还可以使用其他可用于表达条件的属性来正确确定调用并设置正确的 return 值。

在为每个结果初始化单独的游标后,它开始工作了。

 var mockCursorfirstAggregate = new Mock<IAsyncCursor<SampleModel>>();
            mockCursorfirstAggregate.Setup(_ => _.Current).Returns(expectedFirstAggregateResult); 
            mockCursorfirstAggregate
                .SetupSequence(_ => _.MoveNext(It.IsAny<CancellationToken>()))
                .Returns(true)
                .Returns(false);
                
        var mockCursorsecondAggregate = new Mock<IAsyncCursor<SampleModel>>();
            mockCursorsecondAggregate.Setup(_ => _.Current).Returns(expectedSecondAggregateResult); 
            mockCursorsecondAggregate
                .SetupSequence(_ => _.MoveNext(It.IsAny<CancellationToken>()))
                .Returns(true)
                .Returns(false);
                
         this.mockDbContext.SetupSequence(x => x.GetCollection<SampleCollection>(It.IsAny<string>()).Aggregate(It.IsAny<PipelineDefinition<SampleCollection, SampleModel>>(), It.IsAny<AggregateOptions>(), It.IsAny<CancellationToken>()))
            .Returns(mockCursorfirstAggregate.Object)
            .Returns(mockCursorsecondAggregate.Object);