繁体   English   中英

C# 如何模拟 Configuration.GetSection(“foo:bar”).Get <List<string> &gt;()

[英]C# how to mock Configuration.GetSection(“foo:bar”).Get<List<string>>()

我在 config.json 文件中有一个如下所示的列表`

{
  "foo": {
    "bar": [
      "1",
      "2",
      "3"
    ]
  }
}`

我能够在运行时使用

Configuration.GetSection("foo:bar").Get<List<string>>()

我想模拟configuration.GetSection来编写单元测试。

以下语法失败

mockConfigRepo
    .SetupGet(x => x.GetSection("reportLanguageSettings:reportLanguageList").Get<List<string>>())
    .Returns(reportLanguages);

我遇到了同样的问题,发现我需要为数组中的每个元素以及数组节点本身创建一个模拟 IConfigurationSection,然后设置父节点返回子节点,子节点返回它们的值。 在 OP 示例中,它看起来像这样:

        var oneSectionMock = new Mock<IConfigurationSection>();
        oneSectionMock.Setup(s => s.Value).Returns("1");
        var twoSectionMock = new Mock<IConfigurationSection>();
        twoSectionMock.Setup(s => s.Value).Returns("2");
        var fooBarSectionMock = new Mock<IConfigurationSection>();
        fooBarSectionMock.Setup(s => s.GetChildren()).Returns(new List<IConfigurationSection> { oneSectionMock.Object, twoSectionMock.Object });
        _configurationMock.Setup(c => c.GetSection("foo:bar")).Returns(fooBarSectionMock.Object);

PS 我正在使用 Moq,所以请转换为您选择的模拟库。

PPS 如果您对这最终起作用的原因感兴趣,不可模拟的 Get() 方法有什么作用,或者有比 OP 更复杂的场景,阅读本课程可能会有所帮助: https : //github.com/aspnet/Extensions/blob/ release/2.1/src/Configuration/Config.Binder/src/ConfigurationBinder.cs

我能够使用 ConfigurationBuilder 解决它。 希望这会有所帮助

  var appSettings = @"{""AppSettings"":{
            ""Key1"" : ""Value1"",
            ""Key2"" : ""Value2"",
            ""Key3"" : ""Value3""
            }}";

  var builder = new ConfigurationBuilder();

  builder.AddJsonStream(new MemoryStream(Encoding.UTF8.GetBytes(appSettings)));

  var configuration= builder.Build();

您可以尝试其他方法。 例如,您可以尝试在您的测试类中创建一个 ConfigurationBuilder 实例:

string projectPath = AppDomain.CurrentDomain.BaseDirectory.Split(new String[] { @"bin\" }, StringSplitOptions.None)[0];
IConfiguration config = new ConfigurationBuilder()
   .SetBasePath(projectPath)
   .AddJsonFile("config.json")
   .Build();

注意:请不要忘记将您的 config.json 文件也添加到您的测试项目中。

一般来说,如果您在根级别有一个键/值并且您想模拟这段代码:

var threshold = _configuration.GetSection("RootLevelValue").Value;

你可以做:

var mockIConfigurationSection = new Mock<IConfigurationSection>();
mockIConfigurationSection.Setup(x => x.Key).Returns("RootLevelValue");
mockIConfigurationSection.Setup(x => x.Value).Returns("0.15");
_mockIConfiguration.Setup(x => x.GetSection("RootLevelValue")).Returns(mockIConfigurationSection.Object);

如果键/值不在根级别,并且您想要模拟这样的代码:

var threshold = _configuration.GetSection("RootLevelValue:SecondLevel").Value;

您还必须模拟Path

var mockIConfigurationSection = new Mock<IConfigurationSection>();
mockIConfigurationSection.Setup(x => x.Path).Returns("RootLevelValue");
mockIConfigurationSection.Setup(x => x.Key).Returns("SecondLevel");
mockIConfigurationSection.Setup(x => x.Value).Returns("0.15");

依此类推第三级:

var threshold = _configuration.GetSection("RootLevelValue:SecondLevel:ThirdLevel").Value;

您还必须模拟Path

var mockIConfigurationSection = new Mock<IConfigurationSection>();
mockIConfigurationSection.Setup(x => x.Path).Returns("RootLevelValue:SecondLevel");
mockIConfigurationSection.Setup(x => x.Key).Returns("ThirdLevel");
mockIConfigurationSection.Setup(x => x.Value).Returns("0.15");

只是为了补充 Ahamed Ishak 的回答。 将实际对象转换为 JSON 会清理代码并尊重类型。 避免字符串拼写错误等。

        var appSettings = JsonConvert.SerializeObject(new
        {
            Security = new SecurityOptions {Salt = "test"}
        });

        var builder = new ConfigurationBuilder();

        builder.AddJsonStream(new MemoryStream(Encoding.UTF8.GetBytes(appSettings)));

        var configuration = builder.Build();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM