[xUnit.net] 全体で1回だけ行う初期化処理を定義する
テストを作る際、アセンブリ全体で一番最初に一回だけ走る初期化処理を書きたいことがあります。その方法をまとめておきます。
本記事で対象とするのは.NET Core 3.1 または .NET 5です。テストのフレームワークはxUnit.netとします。
.NET Core以降では、個人的に以下が必要になるシーンが時々あります[1]。例にとって進めます。
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
以下は実行したいテストの例です[2]。Encoding.RegisterProvider
の準備無しに実行すると失敗します。
using Microsoft.VisualBasic;
using Xunit;
public class MyTest
{
[Fact]
public void Test()
{
var result = Strings.StrConv("1", VbStrConv.Narrow);
Assert.Equal("1", result);
}
}
1. IClassFixture
xUnit.netの流儀に則った方法です。テストクラスが増えるたびにIClassFixture
を付ける(実装する)のが面倒または忘れがちという欠点はあります。
public class EncodingFixture
{
public EncodingFixture()
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
}
}
public class MyTest : IClassFixture<EncodingFixture>
{
[Fact]
public void Test()
{
var result = Strings.StrConv("1", VbStrConv.Narrow);
Assert.Equal("1", result);
}
}
2. Xunit.DependencyInjection
以下のNuGetを参照します。
詳細はGitHubのREADME等をご覧いただきたいですが、いつものGeneric Hostの流儀通りStartup
クラスを作っておけば、最初に呼び出してくれます。
ロガーやシングルトンサービス等々、調整できる幅が広いです[3]。そういったものも変更したいならば、ついでにEncoding.RegisterProvider
も入れさせてもらうのは良さそうです。サードパーティーのNuGetを追加することになるのがあえて言えば難点です。
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
}
}
3. [ModuleInitializer]
C# 9.0で追加された仕様です。.NET 5以降なら使えます。この方法はそもそもテストに限らず使えます。
今回の例である Encoding.RegisterProvider
であれば最も楽かと思います。
internal static class Initializer
{
[ModuleInitializer]
public static void Initialize()
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
}
}
-
Microsoft.VisualBasic
は、 .NET Core以降ではNuGetで導入できます。https://www.nuget.org/packages/Microsoft.VisualBasic/ ↩︎ -
一例として、テストの時だけ
ITestOutputHelper
をロガーに登録する用途等があります。直接Xunit.DependencyInjectionは使っていませんが参考になる記事です: https://www.meziantou.net/how-to-get-asp-net-core-logs-in-the-output-of-xunit-tests.htm ↩︎
Discussion