App.configファイルを読み取る単純な単体テストプロジェクトを作成しました。ターゲットフレームワークはCore 2.0です。また、Core 2.0コンソールアプリを作成し、自分自身の健全性をチェックして、何も変なことをしていないことを確認しました(.NET 4.6.1単体テストプロジェクトで同じテストに合格しました)。
コンソールアプリはapp.configを正常に読み取りますが、単体テストメソッドが失敗し、その理由がわかりません。両方とも同じapp.config(リンクとして追加されていない)のコピーを使用しており、両方ともSystem.Configuration.ConfigurationManager v4.4.1 NuGetパッケージがインストールされています。
App.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="Test1" value ="This is test 1."/>
<add key="Test2" value ="42"/>
<add key="Test3" value ="-42"/>
<add key="Test4" value="true"/>
<add key="Test5" value="false"/>
<add key="Test6" value ="101.101"/>
<add key="Test7" value ="-1.2345"/>
</appSettings>
</configuration>
ユニットテスト
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Configuration;
namespace ConfigTest
{
[TestClass]
public class UnitTest1
{
[TestMethod()]
public void ConfigTest()
{
foreach (string s in ConfigurationManager.AppSettings.AllKeys)
{
System.Console.WriteLine(s);
System.Diagnostics.Debug.WriteLine(s);
}
//AllKeys.Length is 0? Should be 7...
Assert.IsTrue(ConfigurationManager.AppSettings.AllKeys.Length == 7);
}
}
}
コンソールアプリ
using System;
using System.Configuration;
namespace ConfigTestApp
{
class Program
{
static void Main(string[] args)
{
foreach (string s in ConfigurationManager.AppSettings.AllKeys)
{
Console.WriteLine(s);
System.Diagnostics.Debug.WriteLine(s);
}
//Outputs 7 as expected
Console.WriteLine(ConfigurationManager.AppSettings.AllKeys.Length);
}
}
}
私はまだ.NET Coreの世界全体にかなり慣れていないので、ここでまったく間違ったことをしていますか?ちょっと気が狂ったように感じます...
Xunitテストで同じ問題に遭遇し、ConfigurationManagerのConfigurationのインスタンスを使用してそれを解決しました。 3つのすべてで機能する別の方法を示す前に、静的な(通常の)方法をコア、フレームワーク(単体テストではない)で使用します。
var appSettingValFromStatic = ConfigurationManager.AppSettings["mySetting"];
var appSettingValFromInstance = ConfigurationManager.OpenExeConfiguration(Assembly.GetExecutingAssembly().Location).AppSettings.Settings["mySetting"].Value;
そして、同様の/関連する問題があります。誰かがセクションを取得する必要がある場合、アプリの設定でタイプを変更する必要がありますが、同様のことができます:
<configSections>
<section name="customAppSettingsSection" type="System.Configuration.AppSettingsSection"/>
<section name="customNameValueSectionHandlerSection" type="System.Configuration.NameValueSectionHandler"/>
</configSections>
<customAppSettingsSection>
<add key="customKey" value="customValue" />
</customAppSettingsSection>
<customNameValueSectionHandlerSection>
<add key="customKey" value="customValue" />
</customNameValueSectionHandlerSection>
セクションを取得するコード:
var valFromStatic = ((NameValueCollection)ConfigurationManager.GetSection("customNameValueSectionHandlerSection"))["customKey"];
var valFromInstance = ((AppSettingsSection)ConfigurationManager.OpenExeConfiguration(Assembly.GetExecutingAssembly().Location).GetSection("customAppSettingsSection")).Settings["customKey"].Value;
私もクレイジーだと感じており、コアで設定を行う新しい方法があることを知っていますが、クロスプラットフォームで何かをしたい場合はこれが唯一の方法です。誰かが代替手段を持っているなら、私は非常に興味があります
ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
の呼び出しの結果を確認する場合
そのアセンブリの単体テストの実行中に、必要な構成ファイルの場所を指定する必要があります。
ConfigurationManagerはapp.config
ファイルを使用する代わりに、testhost.dll.config
ファイルを探していました。
これは、netcoreapp2.1
、Microsoft.NET.Test.Sdk
、およびNUnit 3.11
への参照を含むNunit3TestAdapter 3.12.0
を対象とするプロジェクト用でした
ConfigurationManager
やAppSettings
などの静的なConnectionStrings
プロパティに直接アクセスするコードを扱っている場合、ここで与えられた答えはどれも実行可能な回避策を提供しません。
真実は、現時点では不可能です。以下の説明を読んで、理由を理解できます。 https://github.com/dotnet/corefx/issues/22101
ここでサポートを実装するための話があります: https://github.com/Microsoft/vstest/issues/1758
私の意見では、このシナリオは.NET FrameworkとSystem.Configuration.ConfigurationManager
は.NET Standard 2.0ライブラリになりました。
ConfigurationManager
APIは、現在実行中のアプリの構成のみを使用します。単体テストプロジェクトでは、これは、コンソールアプリケーションではなく、テストプロジェクトのapp.configを意味します。
.NET Coreアプリケーションは、従来の「フルフレームワーク」構成システムであるため、app.configまたはConfigurationManager
を使用することは想定されていません。
JSON、XML、またはINI構成ファイルを読み取る代わりにMicrosoft.Extensions.Configuration
を使用することを検討してください。このドキュメントを参照してください。 https://docs.Microsoft.com/en-us/aspnet/core/fundamentals/configuration
github issueのコメントを見て、msbuildファイルに入れることができる回避策を見つけました...
<Target Name="CopyCustomContent" AfterTargets="AfterBuild">
<Copy SourceFiles="app.config" DestinationFiles="$(OutDir)\testhost.dll.config" />
</Target>
これにより、構成データをjson構成ファイルに移植する前に、.NET Coreで既存のテストを簡単に検証できます。
通常、.NET Frameworkプロジェクトでは、実行時に到達できるように、App.configファイルはVisual Studioによって実行可能ファイル(myApp.exe.config)の名前でbinフォルダーにコピーされました。 .NET StandardまたはCore Frameworkではもうありません。 manually bin/debugまたはreleaseフォルダーにファイルをコピーして設定する必要があります。その後、次のようになります:
string AssemblyName = System.IO.Path.GetFileName(System.Reflection.Assembly.GetEntryAssembly().GetName().CodeBase);
AppConfig = (System.Configuration.Configuration)System.Configuration.ConfigurationManager.OpenExeConfiguration(AssemblyName);
ハッキングはできますが、動作する方法は、構成をエントリAssemblyと同じフォルダーにコピーすることです。
[SetUpFixture]
public class ConfigKludge
{
[OneTimeSetUp]
public void Setup() =>
File.Copy(
Assembly.GetExecutingAssembly().Location + ".config",
Assembly.GetEntryAssembly().Location + ".config",
true);
[OneTimeTearDown]
public void Teardown() =>
File.Delete(Assembly.GetEntryAssembly().Location + ".config");
}
このクラスを追加することとは別に、テストプロジェクトにapp.config
ファイルを含めること(コピーオプションなし)のみです。これは、デフォルトのロジックの一種であるため、ビルドステップで<your test project name>.dll.config
として出力フォルダーにコピーする必要があります。
OneTimeSetUpAttribute
のドキュメントに注意してください。
要約:子テストが実行される前にセットアップを実行するために一度呼び出されるメソッドを識別します。
1つのプロジェクトの並列テスト実行では機能するはずですが、2つのテストプロジェクトを同時に実行すると、構成が上書きされるため、明らかな問題が発生する可能性があります。
ただし、 Travis のように、コンテナ化されたテストの実行には引き続き適しています。