gpt4 book ai didi

C# 为对象列表创建 Mock Configuration.GetSection (“Section:SubSection” )

转载 作者:行者123 更新时间:2023-12-04 08:58:26 29 4
gpt4 key购买 nike

客观的
使用 Moq 和 XUnit 创建一个模拟对象,用于加载特定部分“字符/技能”以增强单元测试的覆盖率。
SUT(在某些时候)以这种方式加载设置

var skills = Configuration.GetSection(“Character:Skills”);
从以下应用程序设置:
{
"dummyConfig1": {
"Description": "bla bla bla...",
},
"Character": {
"Name": "John Wick",
"Description": "A retired hitman seeking vengeance for the killing of the dog given to him...",
"Skills": [
{
"Key": "CQC Combat",
"Id": "15465"
},
{
"Key": "Firearms",
"Id": "14321"
},
{
"Key": "Stealth",
"Id": "09674"
},
{
"Key": "Speed",
"Id": "10203"
}
],
"DummyConf2": "more bla bla bla..."
}
以前的阅读
阅读这些帖子(和其他帖子,谷歌搜索的结果),我注意到我们只能使用原始的“字符串”数据类型或新的 Mock 对象(没有设置):
  • Stack Overflow - how to mock Configuration.GetSection(“foo:bar”) ,
  • Mocking IConfiguration extension method
  • Mocking IConfiguration Getvalue() extension method in Unit Test

  • 约束:将 appSetting 文件复制到 TestProject(或创建 MemoryStream)以加载真实设置可以解决这种情况,但测试将是“集成”而不是“单元”;因为存在 I/O 依赖性。
    该方法
    代码的想法(稍后显示)是模拟每个属性(键/ID),然后将它们合并到类似于以下的树中:
  • “字符”------要读取的配置,使用GetSection()然后 Get<T>()
  • “技能”------具有合并属性的配置列表
  • “ key ”-“CQC 实战”------ 原始值 1
  • "Id"- "15465"------ 原始值 2



  • 编码
    var skillsConfiguration = new List<SkillsConfig>
    {
    new SkillsConfig { Key = "CQC Combat" , Id = "15465" },
    new SkillsConfig { Key = "Firearms" , Id = "14321" },
    new SkillsConfig { Key = "Stealh" , Id = "09674" },
    new SkillsConfig { Key = "Speed" , Id = "10203" },
    };

    var configurationMock = new Mock<IConfiguration>();
    var mockConfSections = new List<IConfigurationSection>();

    foreach (var skill in skillsConfiguration)
    {
    var index = skillsConfiguration.IndexOf(skill);

    //Set the Key string value
    var mockConfSectionKey = new Mock<IConfigurationSection>();
    mockConfSectionKey.Setup(s => s.Path).Returns($"Character:Skills:{index}:Key");
    mockConfSectionKey.Setup(s => s.Key).Returns("Key");
    mockConfSectionKey.Setup(s => s.Value).Returns(skill.Key);

    //Set the Id string value
    var mockConfSectionId = new Mock<IConfigurationSection>();
    mockConfSectionId.Setup(s => s.Path).Returns($"Character:Skills:{index}:Id");
    mockConfSectionId.Setup(s => s.Key).Returns("Id");
    mockConfSectionId.Setup(s => s.Value).Returns(skill.Id);

    //Merge the attribute "key/id" as Configuration section list
    var mockConfSection = new Mock<IConfigurationSection>();
    mockConfSection.Setup(s => s.Path).Returns($"Character:Skills:{index}");
    mockConfSection.Setup(s => s.Key).Returns(index.ToString());
    mockConfSection.Setup(s => s.GetChildren()).Returns(new List<IConfigurationSection> { mockConfSectionKey.Object, mockConfSectionId.Object });

    //Add the skill object with merged attributes
    mockConfSections.Add(mockConfSection.Object);
    }

    // Add the Skill's list
    var skillsMockSections = new Mock<IConfigurationSection>();
    skillsMockSections.Setup(cfg => cfg.Path).Returns("Character:Skills");
    skillsMockSections.Setup(cfg => cfg.Key).Returns("Skills");
    skillsMockSections.Setup(cfg => cfg.GetChildren()).Returns(mockConfSections);

    //Mock the whole section, for using GetSection() method withing SUT
    configurationMock.Setup(cfg => cfg.GetSection("Character:Skills")).Returns(skillsMockSections.Object);
    预期结果
    运行原始系统,我得到了各自的实例化列表
    这是屏幕截图:
    appsetting loaded sucessfully
    模拟结果
    上面的代码,我只得到了实例化的列表,但所有的属性都返回空值。
    这是屏幕截图:
    appsetting mocked with null values

    最佳答案

    最后我重构了代码,摆脱了整个foreach阻止并替换列表初始化 var mockConfSections = new List<IConfigurationSection>();使用以下代码,它更简单,更干净。

    var fakeSkillSettings = skillsConfiguration.SelectMany(
    skill => new Dictionary<string, string> {
    { $"Character:Skills:{skillsConfiguration.IndexOf(skill)}:Key", skill.Key },
    { $"Character:Skills:{skillsConfiguration.IndexOf(skill)}:Id" , skill.Id },
    });

    var configBuilder = new ConfigurationBuilder();
    var mockConfSections = configBuilder.AddInMemoryCollection(fakeSkillSettings)
    .Build()
    .GetSection("Character:Skills")
    .GetChildren();
    解释
    由于之前的实现构建了带有模拟节点的配置树,因此需要为每个节点build设置和返回,从而导致解决方案臃肿。
    基于文章 Keeping Configuration Settings in Memory ,我使用 LINQ SelectMany 用扁平的 Key/Id 字典投影列表,然后构建内存配置,最后用“真实节点”模拟设置,从而产生一个模拟设置。

    关于C# 为对象列表创建 Mock Configuration.GetSection (“Section:SubSection” ),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63692671/

    29 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com