app.config没有加载.Net Core MSTests项目

afl*_*pes 16 c# .net-core

我正在研究一个项目,我正在尝试将几个库从.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>
Run Code Online (Sandbox Code Playgroud)

和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"]);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在构建此项目时,将生成SimpleTestsUnits.dll,并使用SimpleTestsUnits.dll文件的同一文件夹中的app.config文件的内容创建SimpleTestsUnits.dll.config.

因此,当我使用VS2017运行单元测试时,"TestKey"的值始终为null,如果我调试到ConfigurationManager.AppSettings,则没有加载密钥.

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

我在这里错过了什么?这不应该有效吗?

Cod*_*ler 13

执行测试时,条目程序集不是包含测试的程序集.您可以通过在测试中添加以下行并进行调试来检查它:

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希望能够找到app.configtesthost.dll.config指定目录.我已经将它复制到这个位置并且测试通过了(稍微修改了配置,见下文).

另一个问题是你的app.config不完全正确.configSectionselement应该是<configuration>root中的第一个.所以只需删除configSections元素为空,或者app.config按以下方式调整元素:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
  </configSections>
  <appSettings>
    <add key="TestKey" value="20" />
  </appSettings>
</configuration>
Run Code Online (Sandbox Code Playgroud)

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

[TestMethod]
public void UnitTest1()
{
    //  Put your Test assembly name here
    Configuration configuration = ConfigurationManager.OpenExeConfiguration(@"SimpleTestsUnits.dll");

    Assert.AreEqual("20", configuration.AppSettings.Settings["TestKey"].Value);
}
Run Code Online (Sandbox Code Playgroud)

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

  • 将此答案标记为问题修复程序,但有没有办法在不更改代码的情况下完成此工作?真正的问题是我移植到.net核心的库使用ConfigurationManager在测试执行期间获得配置,并且使用这种方法我肯定需要更改它的代码. (2认同)

Osk*_*erg 7

我相信,当有一个非常简单的解决方案在不修改被测代码的情况下可以工作时,正确接受的答案会使事情复杂化。

MSTest作为testhost.dll运行,这意味着在.NET核心下执行时,ConfigurationManager正在从testhost.dll.config中读取设置。它将查找testhost.dll所在的testhost.dll.config作为接受的答案状态。没有提到的是,它还将在您拥有测试dll的位置中查找testhost.dll.config。

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

您可以通过在“项目”标签内的MSTest .csproj文件的末尾添加以下MSBuild步骤,轻松地自动执行此操作。

<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>
Run Code Online (Sandbox Code Playgroud)

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