web-dev-qa-db-ja.com

Xunitプロジェクトでの依存性注入

ASP.Net Core MVC Webアプリケーションに取り組んでいます。

ソリューションには2つのプロジェクトが含まれています。1つはアプリケーション用で、もう1つは単体テスト専用のプロジェクトです。

Testsプロジェクトにアプリケーションプロジェクトへの参照を追加しました。

ここでやりたいことは、エンティティフレームワークを介してデータベースと通信するTestsプロジェクトにクラスを作成することです。

私のアプリケーションプロジェクトで行っていたのは、コンストラクター依存関係注入を介してDbContextクラスにアクセスすることでした。

ただし、Startup.csファイルがないため、テストプロジェクトでこれを行うことはできません。このファイルでは、利用可能なサービスを宣言できます。

では、テストクラスでDbContextのインスタンスへの参照を取得するにはどうすればよいですか?

ありがとう

9
Bob5421

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をモックすることをお勧めします。

優れた単体テストの構造

8

Xunit.DependencyInjection を使用できます

2
Mr. Pumpkin

単体テストの場合、コンテキストをモックする必要があります。

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();

TestClassIDisposableTestClass : IDisposable)各テストの後にコンテキストを破棄できるようにします。

https://xunit.github.io/docs/shared-context

0
Paul Adam