DB アクセスにかかわる部分の単体テストについて MicroSoft 公式では、テスト用にローカルに新しく DB をたててテストすることを推奨しています。
公式では XUnit を使用した例で実装していたため、MSTest を使用した実装方法を紹介します。
DB の初期化クラス追加
MSTest のプロジェクトに DB の初期化クラスを追加します。
このクラスでは既存のテスト用 DB があればクリア、最新の情報でテーブルを作成、データの追加を行います。
コードは下記です。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
namespace Example.Server.Tests;
public class TestDatabaseInitializer
{
private const string ConnectionString = @"Server=(localdb)\mssqllocaldb;Database=Temp-TestDB;Trusted_Connection=True;ConnectRetryCount=0";
private static readonly object _lock = new();
private static bool _databaseInitialized;
static TestDatabaseInitializer()
{
lock (_lock)
{
if (!_databaseInitialized)
{
using (var context = CreateContext())
{
context.Database.EnsureDeleted();
context.Database.EnsureCreated();
context.Temp.Add(new Temp { Id = 0, Text = "TestData1" });
context.Temp.Add(new Temp { Id = 0, Text = "TestData2" });
context.Temp.Add(new Temp { Id = 0, Text = "TestData3" });
context.Temp.Add(new Temp { Id = 0, Text = "TestData4" });
context.Temp.Add(new Temp { Id = 0, Text = "TestData4" });
context.Users.AddRange(users);
context.SaveChanges();
}
Console.WriteLine("Database initialized");
_databaseInitialized = true;
}
}
}
public static ExampleDbContext CreateContext()
=> new ExampleDbContext(
new DbContextOptionsBuilder<ExampleDbContext>()
.UseSqlServer(ConnectionString)
.Options);
}
ConnectionString
に接続先を保持しているため、この値をローカルのテスト用 DB に設定することでテスト用 DB を使用することができます。
テストクラス側のコード
テストクラス側のコードは以下のように記述します。
[assembly: ClassCleanupExecution(ClassCleanupBehavior.EndOfClass)]
namespace Example.Server.Controllers.Tests
{
[TestClass()]
public class TempControllerTests
{
private static ExampleDbContext _context;
public TempControllerTests()
{
}
[ClassInitialize]
public static void ClassInitialize(TestContext testContext)
{
_context = TestDatabaseInitializer.CreateContext();
}
}
}
このようにすることで DBContext を使用することができます。
処理の解説
初期化クラスでは DB のテーブル作成と初期データ投入を行います。
複数のクラスから同時アクセスされても良いようにlock
による排他とフラグによる制御を入れます。
またコンテキストを生成するメソッドが静的に定義されているため、コンストラクターも静的にしています。
ただし静的コンストラクターは1度しか実行されないため、lock
による排他とフラグの部分は不要かもしれません。
おわりに
これで、MSTest でテスト用 DB に接続する事ができます。ぜひ参考にしてみてください。
この記事が皆様のコーディングライフの助けになれば幸いです。
参考