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