TL;DR

  • InMemoryDatabaseはサービスプロバイダを共有しない
  • したがってテスト間でデータが共有されない
  • InMemoryDatabaseRootを使って解決する

前提

統合テスト起動時、データベースへ初期データを登録しています。

CustomWebApplicationFactory.cs

public class CustomWebApplicationFactory : WebApplicationFactory<Startup>
{
    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        builder.ConfigureServices(services =>
        {
            services.AddDbContext<MyDBContext>(options =>
            {
                // InMemoryDatabaseを使う
                options.UseInMemoryDatabase("MyTest");
            });
        });

        builder.Configure(app =>
        {
            // DBContextはrootにはなく別スコープにあるので、
            // スコープを作らないと取得できない。
            using (var sp = app.ApplicationServices.CreateScope())
            {
                var context = sp.ServiceProvider.GetRequiredService<MyDBContext>();

                // ここでデータベースへ初期データを登録

                context.SaveChanges();
            }
        });
     }
}

WebApplicationFactoryは、Microsoft.AspNetCore.Mvc.Testingパッケージに用意されているクラスです。TestServerの作成等をやってくれます。

問題

コントローラにインジェクションされるDBコンテキストを見ても、登録したデータが入っていません。

解決策

Issueが上がっていました。
https://github.com/aspnet/EntityFrameworkCore/issues/9613#issuecomment-430722420

先ほどのCustomWebApplicationFactoryクラスを変更します。

CustomWebApplicationFactory.cs

public class CustomWebApplicationFactory : WebApplicationFactory<Startup>
{
    public static readonly InMemoryDatabaseRoot InMemoryDatabaseRoot
    = new InMemoryDatabaseRoot();

    // (省略)
            services.AddDbContext<MyDBContext>(options =>
            {
                options.UseInMemoryDatabase("MyTest", InMemoryDatabaseRoot);
            });
    // (省略)

}

UserInMemoryDatabaseメソッドに、InMemoryDatabaseRootオブジェクトを渡してあげればよいそうです。