.NetCore技术研究-ConfigurationManager在单元测试下的坑

最近在将原有代码迁移.NET Core, 代码的迁移基本很快,当然也遇到了不少坑,重构了不少,后续逐步总结分享给大家。今天总结分享一下ConfigurationManager遇到的一个问题。

先说一下场景:

   迁移.NET Core后,已有的配置文件,我们希望做到兼容,比如说app.config和web.config,

   这样配置文件尽可能地和.NET Framework是一套,尽可能低保持一致。比如:appSettings自定义configSection等等。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="CustomConfigs" type="ClassLibraryNetStandard.CustomConfigHandler, ClassLibraryNetStandard"/>
  </configSections>
  <CustomConfigs>
    <CustomConfig name="service1" order="0" reflectconfig="ClassLibraryNetStandard.TestService, ClassLibraryNetStandard"/>
    <CustomConfig name="service2" order="1" reflectconfig="ClassLibraryNetStandard.TestService2, ClassLibraryNetStandard"/>
  </CustomConfigs>  
  <appSettings>
    <add key="service" value="service1"/>
  </appSettings>
</configuration>

 对于上面配置读取我们做了以下几个事情

   1. 添加Nuget:System.Configuration.ConfigurationManager

   2. 保证原有自定义Section配置相关的代码、读取配置的代码,迁移到.NET Core后编译通过

   3. 修改配置文件、单元测试

 一、添加Nuget:System.Configuration.ConfigurationManager

   搜索System.Configuration.ConfigurationManager:找到Nuget包,并添加引用:

   

二、保证原有自定义Section配置相关的代码、读取配置的代码,迁移到.NET Core后编译通过

  示例代码中,自定义配置类CustomConfig

using System;
using System.Collections.Generic;
using System.Text;

namespace ClassLibraryNetStandard
{
    public class CustomConfig
    {
        public string Name { get; set; }

        public string ReflectConfig { get; set; }

        public int Order { get; set; }
    }
}

  同时对应的Section配置节解析类:CustomConfigHandler,实现接口:System.Configuration.IConfigurationSectionHandler

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;

namespace ClassLibraryNetStandard
{
   public class CustomConfigHandler : System.Configuration.IConfigurationSectionHandler
    {
        public object Create(object parent, object configContext, XmlNode section)
        {
            var configs = new List<CustomConfig>();

            //获取配置文件中自定义节点值  
            foreach (XmlNode childNode in section.ChildNodes)
            {
                string name = null;
                var config = new CustomConfig();
                if (childNode.Attributes["name"] != null)
                {
                    name = childNode.Attributes["name"].Value;
                    config.Name = name;

                    if (childNode.Attributes["order"] != null)
                    {
                        config.Order = Convert.ToInt32(childNode.Attributes["order"].Value);
                    }
                    if (childNode.Attributes["reflectconfig"] != null)
                    {
                        config.ReflectConfig = childNode.Attributes["reflectconfig"].Value;
                    }                  

                    configs.Add(config);
                }
            }

            return configs;
        }
    }
}

    同时,我们编写了一个简单的配置管理类:CustomConfigManager,其中有配置读取方法,直接读取配置文件:

        public static List<CustomConfig> GetCustomConfigs()
        {
            var sectionConfig = System.Configuration.ConfigurationManager.GetSection("CustomConfigs");
            if (sectionConfig != null)
            {
                return  sectionConfig as List<CustomConfig>;
            }

            return null;
        }

  

  这里我们使用了.NET Standard 2.0 library project,代码编译通过:

1>------ 已启动全部重新生成: 项目: ClassLibraryNetStandard, 配置: Debug Any CPU ------
1>C:\Program Files\dotnet\sdk\3.0.100-preview3-010431\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.RuntimeIdentifierInference.targets(151,5): message NETSDK1057: 你正在使用 .NET Core 的预览版。请查看 https://aka.ms/dotnet-core-preview
1>ClassLibraryNetStandard -> C:\Users\***\source\repos\NETFrameworkTest\ClassLibraryNetStandard\bin\Debug\netstandard2.0\ClassLibraryNetStandard.dll
========== 全部重新生成: 成功 1 个,失败 0 个,跳过 0 个 ==========

   三、修改配置文件、单元测试

  添加MSTest单元测试工程:   

  

   增加App.config配置文件:

   

   在单元测试方法中测试配置的读取:

       [TestMethod]
        public void ConfigTest()
        {
            var configs = ClassLibraryNetStandard.CustomConfigManager.GetCustomConfigs();
            Assert.IsNotNull(configs);
        }

  原本以为,肯定可以获取到配置,实际获取的configs是null。

        换了个Console类的应用,同样的配置文件读取,一点没有问题:

      

      对比看了一下这两个工程,发现除了实际编译生成的配置文件名称不同,其他都一样。

      问题肯定出在了单元测试工程上。Google了一下:有以下发现:       

MSTest is running as testhost.dll, which means that ConfigurationManager is reading settings from testhost.dll.config when executing under .NET core. 
It will look for testhost.dll.config where the testhost.dll is located as the accepted answer states.
What is not mentioned is that it will also look for testhost.dll.config in the location where you have your test dlls.

  一句话:MSTest以testhost.dll运行,去取的配置文件是testhost.dll.config

        这太尴尬了,直接无语,不过有两个解决方案:

        1. 直接在单元测试工程中将app.config文件改为:testhost.dll.config

        2. 修改单元测试工程文件,配置编译后事件,动态copy生成testhost.dll.config

       

      试过之后,果真可以了,问题解决,分享给大家。

 

 

周国庆

2019/9/12

转载于:https://www.cnblogs.com/tianqing/p/11514840.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值