C#如何模拟Configuration.GetSection(“foo:bar”)。获取<list <string>&gt;()

时间:2018-05-06 15:46:47

标签: c# unit-testing mocking moq

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

5 个答案:

答案 0 :(得分:7)

我能够使用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();

答案 1 :(得分:6)

通常,如果您在根级别具有键/值,并且想要模拟这段代码:

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

答案 2 :(得分:1)

我遇到了同样的问题,发现我需要为数组中的每个元素以及数组节点本身创建一个模拟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);

P.S。我正在使用Moq,因此请转换为您选择的模拟库。

P.P.S。如果您对这种方法为什么能起作用,不可模仿的Get()方法做什么或比OP具有更复杂的方案感兴趣,那么阅读此类可能会有所帮助:https://github.com/aspnet/Extensions/blob/release/2.1/src/Configuration/Config.Binder/src/ConfigurationBinder.cs

答案 3 :(得分:0)

您可以尝试其他方法。例如,您可以尝试在测试类中创建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文件也添加到测试项目中。

答案 4 :(得分:0)

只需添加Ahamed Ishak的答案即可。将实际对象转换为JSON将清理代码并尊重类型。避免出现字符串输入错误等。

=TIME(0,A1,0)