私は、代わりに別のコンストラクタの呼び出しを返す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は素晴らしいツールであり、可能な限り最もきれいなインターセプトを実現できます(オブジェクト作成やインターフェイスのファクトリを持っていなくても、クラスやオブジェクトの生成はまったく変更されませんが、フリーのライブラリではありません)。実行時にプロキシを作成するのではなく、コンパイル時にコードを挿入するため、メソッドの代行受信を追加するためのシームレスな方法で初期プログラムが変更されます。
.....
この点で優れた点は、コード内で他に何も変更しないため、新しいキーワードを使用してオブジェクトを生成できることです。
私は個人的にファクトリパターンのアプローチを好みますが、クラスに依存関係を注入する必要はありません。
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();
}
}