【问题标题】:app.config not beeing loaded in .Net Core MSTests projectapp.config 未在 .Net Core MSTest 项目中加载
【发布时间】:2018-05-24 22:29:50
【问题描述】:

我正在开发一个项目,我正在尝试将多个库从 .NET Framework 4.5.2 移植到 .NET Core 2,并且在尝试读取单元测试中的旧 app.config appsettings 时遇到了一些问题.为了将问题减少到最低限度的重现场景,我在 VS2017 中创建了以下项目:

我有 app.config 文件:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <appSettings>
    <add key="TestKey" value="20" />
  </appSettings>
  <configSections>
  </configSections>
</configuration>

还有 UnitTest1.cs 文件:

using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Configuration;

namespace SimpleTestsUnits
{
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void FromConfigurationManager()
        {
            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 失败。预期:。 实际:.

我在这里缺少什么?这不应该工作吗?

【问题讨论】:

    标签: c# .net-core


    【解决方案1】:

    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”标记中轻松地自动执行此操作。

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

    来源:(https://github.com/Microsoft/testfx/issues/348#issuecomment-454347131)

    【讨论】:

    • 对我不起作用...在我的情况下,它的位置是“C:\Users\x\.nuget\packages\microsoft.testplatform.testhost\15.5.0\lib \netstandard1.5\testhost.dll.config" 这不是 "$(OutputPath)"
    • 如果 "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 文件在你的输出路径中。
    • 这应该是公认的答案,它无需修改即可工作。如果它对您不起作用,请在 &lt;/Target&gt; 之前添加一个 &lt;Exec Command="env" /&gt; 并在输入测试方法时检查 Assembly.GetEntryAssembly().Location 并查看该位置是否由任何环境变量提示,然后使用该变量而不是 @ 987654326@
    【解决方案2】:

    当您执行测试时,入口程序集不是您的测试程序集。您可以通过在测试中添加以下行并对其进行调试来检查它:

    var configLocation = Assembly.GetEntryAssembly().Location;

    在我的情况下,configLocationc:\Users\myusername\.nuget\packages\microsoft.testplatform.testhost\15.3.0-preview-20170628-02\lib\netstandard1.5\testhost.dll

    所以ConfigurationManager 期望在指定目录中的testhost.dll.config 处找到app.config。我已经将它复制到这个位置并且测试通过了(在稍微修改配置后,见下文)。

    另一个问题是您的 app.config 不完全正确。 configSections 元素应该是 &lt;configuration&gt; 根中的第一个。因此,只需删除 configSections 元素,因为它是空的,或者通过以下方式调整您的 app.config

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <configSections>
      </configSections>
      <appSettings>
        <add key="TestKey" value="20" />
      </appSettings>
    </configuration>
    

    当然,将配置文件放在testhost.dll 附近是一种不好的方式。您可以使用 ConfigurationManager.OpenExeConfiguration 调用更改 ConfigurationManager 加载应用程序配置的路径:

    [TestMethod]
    public void UnitTest1()
    {
        //  Put your Test assembly name here
        Configuration configuration = ConfigurationManager.OpenExeConfiguration(@"SimpleTestsUnits.dll");
    
        Assert.AreEqual("20", configuration.AppSettings.Settings["TestKey"].Value);
    }
    

    但不幸的是,这种方法需要修改您的测试代码。

    【讨论】:

    • 将此答案标记为问题修复程序,但是有没有办法在不更改代码的情况下使其工作?真正的问题是我要移植到 .net 核心的库在测试执行期间使用 ConfigurationManager 来获取配置,使用这种方法我肯定需要更改它的代码。
    【解决方案3】:

    你可以试试这个类的大小。

    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;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2020-03-20
      • 2010-12-17
      • 1970-01-01
      • 2016-10-28
      • 2021-12-11
      • 2017-12-15
      • 2019-01-17
      相关资源
      最近更新 更多