automapperを6.1.1から6.2.1へバージョンアップしたら例外がスローされた

開発の区切りが良かったのでライブラリを一斉にアップデートしたところAutoMapperの初期化のタイミングでテストがコケるようになりました。例外は以下の内容です。

System.InvalidOperationException: 'Mapper already initialized. You must call Initialize once per application domain/process.' 

特に初期化処理で何かしているわけではなく、以前のバージョンでは動作していたのでナンノコッチャと調べたところ行き着いたのがこちら。

Version 6.2.0 - System.InvalidOperationException: 'Mapper already initialized. You must call Initialize once per application domain/process.' · Issue #2405 · AutoMapper/AutoMapper

最後のコメントにAdd Mapper.Reset back · Issue #2404 · AutoMapper/AutoMapperを参照してねと書いてあるので参照すると、すでにClosed担っていました。

さらにその中でExtension Doesn't Work with AutoMapper 6.2.0 In Integration Tests · Issue #36 · AutoMapper/AutoMapper.Extensions.Microsoft.DependencyInjectionが参照先とのことでようやく本題にたどり着けたらしい。

そもそもこの事象はAutoMapperの初期化を2回実行するときに例外がスローされることに端を発している。ただ、テストを実行するときにテストごとにすでに初期化済みのAutoMapperを再度初期化しようとするため2回目以降のテストでは再初期化となり例外がスローされるようです。

結局どう対応すればいいかについてはAutoMapper 6.2.1 ReleasedのリリースノートにあるConfiguration — AutoMapper documentationのとおりで、テスト実行時にStartup.csを呼ぶ前にMapper.Reset()を呼び出せばOKでした。

var builder = new ConfigurationBuilder().SetBasePath(Path.GetFullPath("."))
                  .AddJsonFile("appsettings.Test.json", true, true).AddEnvironmentVariables();

var hostBuilder = new WebHostBuilder();
var configurationRoot = builder.Build();
hostBuilder.UseConfiguration(configurationRoot);

// ここでMapper#Resetをコールする
Mapper.Reset();
Server = new TestServer(hostBuilder.UseStartup<Startup>().UseSerilog());

Client = Server.CreateClient();

なお、Configuration — AutoMapper documentationにも記述がありますが、

Reset should not be used in production code. It is intended to support testing scenarios only.

とあるため、本番コードではこの内容は記述しないようにしましょう。

C# 7.0 in a Nutshell: The Definitive Reference

C# 7.0 in a Nutshell: The Definitive Reference