【问题标题】:How to mock two same mongo collection with different results?如何以不同的结果模拟两个相同的 mongo 集合?
【发布时间】:2021-01-31 10:36:05
【问题描述】:

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

下面的示例代码

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);

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

【问题讨论】:

  • 不要使用它。IsAny?并为特定选项提供不同的结果
  • 任何示例?

标签: mongodb unit-testing mocking moq


【解决方案1】:

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

如果您确定测试中的哪个管道调用将首先执行,您可以使用SetupSequence 来控制返回值。您已经在 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);   

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

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

【讨论】:

  • 嗨,提利昂,在我的场景中,两个管道阶段仅相同,但逻辑不同。如何使用此示例的设置顺序来控制它。执行顺序将与提供的示例相同。
【解决方案2】:

为每个结果初始化单独的光标后,它就可以工作了。

 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); 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-07-25
    • 1970-01-01
    • 1970-01-01
    • 2019-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多