努力単位テストのためのShim DbContext ctor

effort entity-framework microsoft-fakes shim unit-testing

質問

私は、代わりに別のコンストラクタの呼び出しを返すvar context = new MyDbContext()を傍受したいと思います。

EFfortの素晴らしい点は、 単体テスト用の簡単なメモリ内データベースをセットアップすることです。

var connection = Effort.DbConnectionFactory.CreateTransient();
var testContext = new MyDbContext(connection);

しかし、そのcontextをリポジトリに注入する必要があります。

public FooRepository(MyDbContext context) { _context = context; }

var context = new MyDbContext()傍受して、 testContext返すことはtestContextですか?

using (var context = new MyDbContext()) {
    // this way, my code isn't polluted with a ctor just for testing
}

受け入れられた回答

(編集:私はこれが実際に他のctor呼び出しを返すわけではないことに気付きました。

理解した。あなたがそれをする方法を知っていれば十分に簡単です:

        [TestMethod]
        public void Should_have_a_name_like_this()
        {
            // Arrange
            var connection = Effort.DbConnectionFactory.CreateTransient();
            ShimSolrDbContext.Constructor = context => new SolrDbContext(connection);

            // Act


            // Assert

        }

そしていつものように、EFfortはこのコンストラクタをDbContextクラスに必要とします:

public class SomeDbContext
{
    public SomeDbContext() : base("name=Prod")
    {
    }

    // EFfort unit testing ctor
    public SomeDbContext(DbConnection connection) : base(connection, contextOwnsConnection: true) {
        Database.SetInitializer<SolrDbContext>(null);
    }
}

しかし、それはRepoが特別なTransient接続を気楽に知らないことを意味します:

public class SomeRepository
{
    public void SomeMethodName()
    {
        using (var context = new SomeDbContext())
        {
            // self-contained in repository, no special params
            // and still calls the special test constructor
        }
    }
}

人気のある回答

可能な選択肢は2つあります。ファクトリを使用するか、Aspect向けのプログラミング(PostSharpなど)

この記事を参照してください: http : //www.progware.org/Blog/post/Interception-and-Interceptors-in-C-(Aspect-oriented-programming).aspx

PostSharp(AOP)の使用

PostSharpは素晴らしいツールであり、可能な限り最もきれいなインターセプトを実現できます(オブジェクト作成やインターフェイスのファクトリを持っていなくても、クラスやオブジェクトの生成はまったく変更されませんが、フリーのライブラリではありません)。実行時にプロキシを作成するのではなく、コンパイル時にコードを挿入するため、メソッドの代行受信を追加するためのシームレスな方法で初期プログラムが変更されます。
.....
この点で優れた点は、コード内で他に何も変更しないため、新しいキーワードを使用してオブジェクトを生成できることです。

DIと工場パターンの使用

私は個人的にファクトリパターンのアプローチを好みますが、クラスに依存関係を注入する必要はありません。

public interface IDbContextFactory<T> where T : DbContext {
    T Create();
}

public class TestDbContextFactory : IDbContextFactory<MyDbContext> {
    public MyDbContext Create() {
        var connection = Effort.DbConnectionFactory.CreateTransient();
        var testContext = new MyDbContext(connection);
        return testContext;
    }
}

public class FooRepository {
    MyDbContext _context;
    public FooRepository(IDbContextFactory<MyDbContext> factory) { 
        _context = factory.Create(); 
    }
}



ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ