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

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

先说一下场景:web

   迁移.NET Core后,已有的配置文件,咱们但愿作到兼容,好比说app.config和web.config,app

   这样配置文件尽量地和.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.ConfigurationManagerspa

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

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

 1、添加Nuget:System.Configuration.ConfigurationManagerhtm

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

   

2、保证原有自定义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 个 ==========

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

  添加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

相关文章
相关标签/搜索