.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
.NetCore技术研究-ConfigurationManager在单元测试下的坑的更多相关文章
- .NetCore技术研究-一套代码同时支持.NET Framework和.NET Core
在.NET Core的迁移过程中,我们将原有的.NET Framework代码迁移到.NET Core.如果线上只有一个小型的应用还好,迁移升级完成后,只需要维护.NET Core这个版本的代码. 但 ...
- .NetCore技术研究-.NET Core迁移前的准备工作
前段时间迁移.NET Core做了大量的试水和评估,今天整理一下分享给大家.大致有以下几个部分: 1. .NET Core的由来 2. 为什么要迁移.NET Core 3. .NET Core3.X主 ...
- .NetCore技术研究-EntityFramework Core 3.0 Preview
前段时间.Net Core 3.0 发布了,Entity Framework Core 3.0 也发布了Preview版.假期用了一上午大致研究了一遍,同时又体验了一把Visual Studio 20 ...
- .NET Core技术研究系列-索引篇
随着.NET Core相关技术研究的深入,现在将这一系列的文章,整理到一个索引页中,方便大家翻阅查找,同时,后续也会不断补充进来. .NET Core技术研究-WebApi迁移ASP.NET Core ...
- 重复数据删除(De-duplication)技术研究(SourceForge上发布dedup util)
dedup util是一款开源的轻量级文件打包工具,它基于块级的重复数据删除技术,可以有效缩减数据容量,节省用户存储空间.目前已经在Sourceforge上创建项目,并且源码正在不断更新中.该工具生成 ...
- 伪AP检测技术研究
转载自:http://www.whitecell-club.org/?p=310 随着城市无线局域网热点在公共场所大规模的部署,无线局域网安全变得尤为突出和重要,其中伪AP钓鱼攻击是无线网络中严重的安 ...
- Azure IoT 技术研究系列2-起步示例之设备注册到Azure IoT Hub
上篇博文中,我们主要介绍了Azure IoT Hub的基本概念.架构.特性: Azure IoT 技术研究系列1-入门篇 本文中,我们继续深入研究,做一个起步示例程序:模拟设备注册到Azure IoT ...
- selenium相关技术研究(从1.0-3.0)
注: 以下内容引自http://www.cnblogs.com/hhudaqiang/p/6550135.html Selenium相关技术研究(从1.0-3.0) 好吧,最近看wxpython有点多 ...
- 【转】手把手教你读取Android版微信和手Q的聊天记录(仅作技术研究学习)
1.引言 特别说明:本文内容仅用于即时通讯技术研究和学习之用,请勿用于非法用途.如本文内容有不妥之处,请联系JackJiang进行处理! 我司有关部门为了获取黑产群的动态,有同事潜伏在大量的黑产群 ...
随机推荐
- JS构建多端应用
JS构建多端应用 一,需求与介绍 1.1,介绍 1,Taro 是一套遵循 React语法规范的 多端开发 解决方案.现如今市面上端的形态多种多样,Web.React-Native.微信小程序等各种端大 ...
- Cocos经典游戏教程之仿皇室战争
版权声明: 本文原创发布于博客园"优梦创客"的博客空间(网址:http://www.cnblogs.com/raymondking123/)以及微信公众号"优梦创客&qu ...
- A solution to the never shortened to-do list
I once told my younger sister my learning system, and the basic five doctrines of my methodology. Bu ...
- 7、数组中添加元素(test5.java)
前文提到了系统函数,arraycopy(),这是一个强大的函数,根据它的特性便可以看出由于他的特殊性质,加以利用的话,就在数组中添加元素,但这样的方式会造成的结果就是,添加n个元素,那么原数组中倒数n ...
- Axure 使用 简单入门
1.Axure 简介 Axure是快速原型工具,简单来说就是把自己的web或app想法快速的展示出来的工具.具体信息百科:https://baike.baidu.com/item/axure%20rp ...
- Web很脆弱,SQL注入要了解
SQL注入 所谓SQL注入,就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令. 通过一下的例子更形象的了解SQL注入: 有一个Login ...
- Spark1——介绍
1.Spark是什么 Spark是一个用来实现快速而通用的集群计算的平台. 2.Spark是一个大一统的软件栈 Spark项目包含多个紧密集成的组件.首先Spark的核心是一个对由很多计算任务组成的. ...
- 记录 Java 的 BlockingQueue 中的一些坑
最近学习了 BlockingQueue,发现 java 的 BlockingQueue 并不是每一个实现都按照 BlockingQueue 的语意来的,其中有不少坑. 直接上代码吧: 1.关于Prio ...
- Python-PostgreSQL的使用
一.安装PostgreSQL模块 yum install postgresql-devel pip3 install psycopg2 注意:安装时遇到./psycopg/psycopg.h:35:2 ...
- 关于js-xlsx的使用
写在前头,本人是名Java开发人员,偶尔在前端打打酱油,写出的代码或许存在问题,请路过的大神一一指正,不吝感激. 最近公司准备做一些关于Excel 数据导入和导出相关需求,之前有在开源社区看到说比起纯 ...