ASP.Net Core MVC Webアプリケーションに取り組んでいます。
ソリューションには2つのプロジェクトが含まれています。1つはアプリケーション用で、もう1つは単体テスト専用のプロジェクトです。
Testsプロジェクトにアプリケーションプロジェクトへの参照を追加しました。
ここでやりたいことは、エンティティフレームワークを介してデータベースと通信するTestsプロジェクトにクラスを作成することです。
私のアプリケーションプロジェクトで行っていたのは、コンストラクター依存関係注入を介してDbContextクラスにアクセスすることでした。
ただし、Startup.csファイルがないため、テストプロジェクトでこれを行うことはできません。このファイルでは、利用可能なサービスを宣言できます。
では、テストクラスでDbContextのインスタンスへの参照を取得するにはどうすればよいですか?
ありがとう
DbContext
を解決する独自のサービスプロバイダーを実装できます。
public class DbFixture
{
public DbFixture()
{
var serviceCollection = new ServiceCollection();
serviceCollection
.AddDbContext<SomeContext>(options => options.UseSqlServer("connection string"),
ServiceLifetime.Transient);
ServiceProvider = serviceCollection.BuildServiceProvider();
}
public ServiceProvider ServiceProvider { get; private set; }
}
public class UnitTest1:IClassFixture<DbFixture>
{
private ServiceProvider _serviceProvide;
public UnitTest1(DbFixture fixture)
{
_serviceProvide = fixture.ServiceProvider;
}
[Fact]
public void Test1()
{
using (var context = _serviceProvider.GetService<SomeContext>())
{
}
}
}
ただし、単体テスト内でEFを使用することはお勧めできません。DbContextをモックすることをお勧めします。
Xunit.DependencyInjection を使用できます
単体テストの場合、コンテキストをモックする必要があります。
Moqと呼ばれる、モック用の素晴らしいnugetパッケージがあります。
あなたが始めるためのいくつかの助け:
public ClassName : IDisposable
{
private SomeClassRepository _repository;
private Mock<DbSet<SomeClass>> _mockSomeClass;
public ClassName()
{
_mockSomeClass = new Mock<DbSet<SomeClass>>();
var mockContext = new Mock<IApplicationDbContext>();
mockContext.SetupGet(c => c.SomeClass).Returns(_mockSomeClass.Object);
_repository = new SomeClassRepository(mockContext.Object);
}
public void Dispose()
{
// Anything you need to dispose
}
[Fact]
public void SomeClassTest()
{
var someClass = new SomeClass() { // Initilize object };
_mockSomeClass.SetSource(new[] { someClass });
var result = _repository.GetSomethingFromRepo( ... );
// Assert the result
}
}
統合テストの場合も同じことを行いますが、セットアップは次のとおりです。
_context = new ApplicationDbContext();
TestClass
がIDisposable
(TestClass : IDisposable
)各テストの後にコンテキストを破棄できるようにします。