C# app.config未加载到.Net Core MSTests项目中
我正在进行一个项目,我正在尝试将几个库从.NET Framework 4.5.2移植到.NET Core 2,并且在单元测试中尝试读取遗留的app.config appsettings时遇到了一些问题。为了将问题降低到最低限度,我在VS2017中创建了以下项目: 我有app.config文件:C# app.config未加载到.Net Core MSTests项目中,c#,.net-core,C#,.net Core,我正在进行一个项目,我正在尝试将几个库从.NET Framework 4.5.2移植到.NET Core 2,并且在单元测试中尝试读取遗留的app.config appsettings时遇到了一些问题。为了将问题降低到最低限度,我在VS2017中创建了以下项目: 我有app.config文件: 以及UnitTest1.cs文件: 使用Microsoft.VisualStudio.TestTools.UnitTesting; 使用系统配置; 名称空间SimpleTestsUnits { [测
以及UnitTest1.cs文件:
使用Microsoft.VisualStudio.TestTools.UnitTesting;
使用系统配置;
名称空间SimpleTestsUnits
{
[测试类]
公共类UnitTest1
{
[测试方法]
配置管理器()中的公共void
{
Assert.AreEqual(“20”,ConfigurationManager.AppSettings[“TestKey”]);
}
}
}
在构建此项目时,将生成SimpleTestsUnits.dll,并使用SimpleTestsUnits.dll文件的同一文件夹中的app.config文件内容创建SimpleTestsUnits.dll.config
因此,当我使用VS2017运行单元测试时,“TestKey”的值总是空的,如果我调试到ConfigurationManager.AppSettings中,那里没有加载密钥
引发异常:
'Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException'
在Microsoft.VisualStudio.TestPlatform.TestFramework.dll中存在异常
类型
'Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException'
发生在Microsoft.VisualStudio.TestPlatform.TestFramework.dll中,但
未在用户代码Assert.AreEqual中处理失败。预期:。
实际值:
我错过了什么?这不应该起作用吗?执行测试时,条目程序集不是包含测试的程序集。您可以通过在测试中添加以下行并对其进行调试来检查它:
var configLocation=Assembly.GetEntryAssembly().Location代码>
在我的例子中,configLocation
是c:\Users\myusername\.nuget\packages\microsoft.testplatform.testhost\15.3.0-preview-20170628-02\lib\netstandard1.5\testhost.dll
因此ConfigurationManager
希望在指定目录中的testhost.dll.config
中找到app.config
。我已经将它复制到这个位置,测试通过了ok(在稍微修改配置后,见下文)
另一个问题是app.config不完全正确configSections
元素应该是
根目录中的第一个元素。所以只要删除configSections
元素,因为它是空的,或者按照以下方式调整app.config
:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
</configSections>
<appSettings>
<add key="TestKey" value="20" />
</appSettings>
</configuration>
但不幸的是,这种方法需要修改测试中的代码。MSTest以“testhost.dll”运行,这意味着ConfigurationManager在.NET core下执行时正在从“testhost.dll.config”读取设置。它将在“testhost.dll”所在的位置查找“testhost.dll.config”,但也会在您拥有测试dll的位置查找“testhost.dll.config”
因此,将资源管理器中的配置文件复制或重命名为“testhost.dll.config”将解决此问题
通过将以下MSBuild步骤添加到MSTest.csproj文件末尾的“Project”标记中,可以轻松地实现自动化
来源:()你可以试试这个类的大小
public static class AppConfig
{
const string Filename = "app.config";
static readonly Configuration Configuration;
static AppConfig()
{
try
{
Configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
if (!Configuration.HasFile)
throw new ConfigurationErrorsException();
}
catch
{
try
{
var configmap = new ExeConfigurationFileMap
{
ExeConfigFilename = Filename
};
Configuration = ConfigurationManager.OpenMappedExeConfiguration(configmap, ConfigurationUserLevel.None);
}
catch
{
}
}
}
public static string Get(string key, string @default = "")
{
return Configuration?.AppSettings?.Settings[key]?.Value ?? @default;
}
}
将此答案标记为问题修复程序,但是否有一种方法可以在不更改代码的情况下实现此功能?真正的问题是,我要移植到.net core的库在测试执行期间使用ConfigurationManager来获取配置,使用这种方法,我肯定需要更改它的代码。对我来说不起作用。。。在我的例子中,它所查找的位置是“C:\Users\x\.nuget\packages\microsoft.testplatform.testhost\15.5.0\lib\netstandard1.5\testhost.dll.config”,而不是“C:\Users\x\.nuget\packages\microsoft.testplatform.testhost\15.5.0\lib\netstandard1.5\testhost.dll.config”中的“$(输出路径)”实际上存在,它可能更喜欢读取该文件。但是,如果您可以删除“C:\Users\x\.nuget\packages\microsoft.testplatform.testhost\15.5.0\lib\netstandard1.5\testhost.dll.config”文件,它可能会在您的输出路径中使用testhost.dll.config文件。这应该是可以接受的答案,无需修改即可工作。如果它不适合您,请在
之前添加一个
,并在输入测试方法时检查Assembly.GetEntryAssembly().Location
,查看是否有任何环境变量提示该位置,然后使用该变量而不是$(OutputPath)
<Target Name="CopyAppConfig" AfterTargets="Build" DependsOnTargets="Build">
<CreateItem Include="$(OutputPath)$(AssemblyName).dll.config">
<Output TaskParameter="Include" ItemName="FilesToCopy"/>
</CreateItem>
<Copy SourceFiles="@(FilesToCopy)" DestinationFiles="$(OutputPath)testhost.dll.config" />
</Target>
public static class AppConfig
{
const string Filename = "app.config";
static readonly Configuration Configuration;
static AppConfig()
{
try
{
Configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
if (!Configuration.HasFile)
throw new ConfigurationErrorsException();
}
catch
{
try
{
var configmap = new ExeConfigurationFileMap
{
ExeConfigFilename = Filename
};
Configuration = ConfigurationManager.OpenMappedExeConfiguration(configmap, ConfigurationUserLevel.None);
}
catch
{
}
}
}
public static string Get(string key, string @default = "")
{
return Configuration?.AppSettings?.Settings[key]?.Value ?? @default;
}
}