繁体   English   中英

app.config 未加载到 .Net Core MSTests 项目中

[英]app.config not beeing loaded in .Net Core MSTests project

我正在做一个项目,我正在尝试将几个库从 .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”的值始终为 null,如果我调试到 ConfigurationManager.AppSettings,则那里没有加载密钥。

抛出的异常:Microsoft.VisualStudio.TestPlatform.TestFramework.dll 中的 'Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException'但未在用户代码中处理 Assert.AreEqual 失败。 预期:<20>。 实际:<(空)>。

我在这里错过了什么? 这不应该工作吗?

MSTest 作为“testhost.dll”运行,这意味着 ConfigurationManager 在 .NET core 下执行时正在从“testhost.dll.config”读取设置。 它会在“testhost.dll”所在的位置查找“testhost.dll.config”,但它还会在您拥有测试 dll 的位置查找“testhost.dll.config”。

因此,将资源管理器中的配置文件复制或重命名为“testhost.dll.config”将解决问题。

您可以通过将以下 MSBuild 步骤添加到 MSTest .csproj 文件末尾的“项目”标记中轻松实现此操作。

<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

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

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元素应该是<configuration>根中的第一个元素。 因此,只需删除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);
}

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

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

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

我实施了Oskar Sjöberg提出的解决方案。 在我们开始使用多目标之前,它适用于我们的解决方案。

Oskar 提供的 MSBuild 步骤将尝试从未用作 output 构建目录的位置复制文件。 它会产生一个错误,因为它找不到它正在寻找的app.config文件。

我最终将Condition="'$(OutDir)' != ''"添加到目标定义中。

注意:我没有在许多平台或许多项目 styles 上对此进行测试。这可能会阻止复制发生。

然后看起来像这样:

<Target Name="CopyAppConfig" AfterTargets="Build" DependsOnTargets="Build" Condition="'$(OutDir)' != ''">
  <CreateItem Include="$(OutputPath)$(AssemblyName).dll.config">
    <Output TaskParameter="Include" ItemName="FilesToCopy" />
  </CreateItem>
  <Copy SourceFiles="@(FilesToCopy)" DestinationFiles="$(OutputPath)testhost.dll.config" />
</Target>

顺便说一句,我想对该帖子发表评论,但我还没有足够的声誉。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM