【问题标题】:How to mock IDocumentClient using Moq?如何使用 Moq 模拟 IDocumentClient?
【发布时间】:2020-10-27 06:34:33
【问题描述】:

我是单元/集成测试的新手,也是 .NET 世界的新手。

问题 1:在其中一个集成测试中,我必须传递一个(模拟的)IConfiguration 变量,我目前将其构建为

var mockConfig = GetConfiguration();

    private static IConfiguration GetConfiguration() =>
        new ConfigurationBuilder()
            .SetBasePath($"{Directory.GetCurrentDirectory()})
            .AddJsonFile("appSettings.json", true)
            .AddCommonVariables()
            .Build();

试用 1:我已经尝试过这样做

    private static Mock<IConfiguration> GetConfiguration() =>
        new Mock<IConfiguration>(new ConfigurationBuilder()
            .SetBasePath($"{Directory.GetCurrentDirectory()})
            .AddJsonFile("appSettings.json", true)
            .AddCommonVariables()
            .Build());

但是,它例外

不能为接口模拟传递构造函数参数。

试用 2:我尝试使用 Moq 的设置选项进行创建

    private static Mock<IConfiguration> GetMockConfiguration()
    {
        var _mockConfigurationBuilder = new Mock<ConfigurationBuilder>();

        //How to setup these methods?
        _mockConfigurationBuilder.Setup(x => x.SetBasePath(It.IsAny<String>())).Returns();
        -_mockConfigurationBuilder.Setup(x => x.AddJsonFile()).Returns()
    }

但我不确定如何设置这些方法。

问题 2:最终模拟 IDocumentClient,我用它来查询我的实体

_cosmosWrapper = new CosmosWrapper(mockLogger.Object, mockConfig.Object);用作

private readonly IDocumentClient _documentClient;
public CosmosWrapper(ILogger<CosmosWrapper> logger, IConfiguration config)
{
  var cosmosConnectionSecretKey = config["cosmosSecretName"];
  var cosmosConnectionString = config[cosmosConnectionSecretKey];
  var cosmosInfo = ConnectionStringParser.Parse(cosmosConnectionString);
  _documentClient = new DocumentClient(new Uri(cosmosInfo["AccountEndpoint"]), cosmosInfo["AccountKey"]);
}

更新:

我不得不通过创建一个 cosmos 连接类来重构文档客户端的设置。

mock - cosmos 连接的设置是,

    var cosmosConnection = new Mock<ICosmosConnection>();

    cosmosConnection.Setup(c => c.CosmosInfo)
        .Returns(new Dictionary<string, string>(new List<KeyValuePair<string, string>>
        {
            new KeyValuePair<string, string>("AccountEndpoint", "//string1.string2")
        }));

最后,为了模拟文档客户端,我从How to (should I) mock DocumentClient for DocumentDb unit testing? 那里得到了一些想法

并根据我的需要实现了更多辅助方法。

private static void SetupProvider(Mock<IFakeDocumentQuery<MyClass>> mockDocumentQuery,
    Mock<IQueryProvider> provider)
{
    provider.Setup(p => p.CreateQuery<MyClass>(It.IsAny<Expression>())).Returns(mockDocumentQuery.Object);
    mockDocumentQuery.As<IQueryable<MyClass>>().Setup(x => x.Provider).Returns(provider.Object);
}

private static void SetupMockForGettingEntities(Mock<IDocumentClient> mockDocumentClient,
    IMock<IFakeDocumentQuery<MyClass>> mockDocumentQuery)
{
    mockDocumentClient.Setup(c => c.CreateDocumentQuery<MyClass>(It.IsAny<Uri>(), It.IsAny<FeedOptions>()))
        .Returns(mockDocumentQuery.Object);
}

【问题讨论】:

  • 你能展示CosmosWrapper类对IConfiguration的作用吗?它是如何使用它的,需要模拟什么行为?
  • @NateBarbettini 我已经编辑了我的问题以反映我的问题。
  • 这能回答你的问题吗? Populate IConfiguration for unit tests
  • @PavelAnikhouski 挖掘它,我找到了stackoverflow.com/questions/43618686/…,我猜这意味着我不应该在我的目录[基础、集成、单元测试等]中模拟 ConfiguraionBuilder,而是直接使用它。跨度>

标签: unit-testing .net-core integration-testing azure-cosmosdb moq


【解决方案1】:

在 Trial-1 下,错误表明您不应传递任何构造函数参数,例如做

private static Mock<IConfiguration> GetConfiguration() {
    var mock = new Mock<IConfiguration>();
    mock.SetupGet(p => p[It.IsAny<string>()]).Returns(string.Empty);
    // or if you want to return specific values:
    mock.SetupGet(p => p[cosmosConnectionSecretKey]).Returns("foo");
    return mock;
}

编辑:请参阅@Pavel Anikhouski 的评论,了解一种可能更清洁的方式来实现您的目标,而无需使用起订量。

【讨论】:

  • @Chaipau 我不确定IConfigurationBuilder 是如何影响这一点的,但我更新了我的答案以说明如何模拟索引器吸气剂。
猜你喜欢
  • 2012-03-18
  • 2010-10-19
  • 2016-09-30
  • 2019-10-06
  • 1970-01-01
  • 2012-06-01
  • 2018-12-27
  • 2019-06-16
  • 2012-07-22
相关资源
最近更新 更多