2017-07-10 10 views
1

私はいくつかのコードを持っています(C#.Net Core WebAPI)私は単体テストをしたいが、依存関係は私に少し奇妙に見えます。IOptionパターン - ユニットのテストとレイヤーの通過

コードは、DbContextとリポジトリの両方が同じ依存性を持っている

...今まで、最初はOKだった。ネットコアWebAPIのを、使用してMongoDBのにアクセスするために(私はウェブ上で発見)いくつかのサンプルコードから来ました - とリポジトリはとにかくDbContextへを通してそれを渡す - リポジトリがDbContextインスタンスとして:

public class LogItemRepository : ILogItemRepository 
    { 
    private readonly DbContext _context = null; 

    public LogItemRepository(IOptions<DbSettings> settings) 
    { 
     _context = new DbContext(settings); 
    } 

を...

public class DbContext 
    { 
    private readonly IMongoDatabase _database = null; 

    public DbContext(IOptions<DbSettings> settings) 
    { 
     var client = new MongoClient(settings.Value.ConnectionString); 
     if (client != null) 
     _database = client.GetDatabase(settings.Value.Database); 
    } 

    public IMongoCollection<LogItem> LogItemsCollection 
    { 
     get 
     { 
     return _database.GetCollection<LogItem>("LogItem"); 
     } 
    } 
    } 
} 

私はOptions patternに精通していませんが、素早く読んでみればよかったです。しかし、私は子の依存関係(オプション)、親の依存関係(上記の例のように)を作るのが良い方法であるとは確信していません。

代わりに、IDbContextというインターフェースを作成して、それをリポジトリーの依存関係として使用する必要がありますか?これは私が過去にやったことですが、これがオプションパターンを破るかどうかはわかりません。

私はこれが主観的だと思っていますが、他にも入力したいと思います。

おかげ ティム

+2

主に意見に基づいていますが、一般的な方法はリポジトリのコンストラクタ内でdbコンテキストをインスタンス化しないことです。リポジトリはコンテキストに密接に結びついています。あなたのOPで述べたように抽象を注入してください。コンテキストのみがNkosiのコメントでオプションの抽象度 – Nkosi

+0

+1に依存しているようです。リポジトリがコンテキストをインスタンス化すると、あらゆる種類の問題が発生します。 5つのリポジトリは潜在的に5つのコンテキストを使用することになります。つまり、渡されたエンティティへの参照/返されたコンテキストは、コンテキストの範囲外に置かれるか、コンテキスト間でエンティティを分離/再接続するための厄介な配線です。単体テスト(TDD/BDDテストのように)では、コンテキストレベルでモックしようとするのではなく、リポジトリレベルでMockをオフにします。 dbとの統合テストでは、リポジトリをテストできます。 –

答えて

1

主に意見をベースに置きながら、一般的な方法は、リポジトリのコンストラクタ内デシベルコンテキストをインスタンス化しないことです。リポジトリはコンテキストに密接に結びついています。あなたのOPで述べたように抽象を注入してください。

私はここで毛を割っているかもしれませんが、提供されている例ではまだ締め付けが強すぎます。

まず抽象的文脈

public interface IDbContext { 
    IMongoCollection<LogItem> LogItemsCollection { get; } 
} 

ともオプションが組成物のルート(スタートアップ)で必要とされ、これまで何をしてIMongoDatabase

public class DbContext : IDbContext { 
    private readonly IMongoDatabase database = null; 

    public DbContext(IMongoDatabase database) 
     this.database = database; 
    } 

    public IMongoCollection<LogItem> LogItemsCollection { 
     get { 
      return database.GetCollection<LogItem>("LogItem"); 
     } 
    } 
} 

明示的な依存関係も設定しサービスを提供しています。拡張メソッドでカプセル化することも考えられます。今リポジトリを残し

services.AddScoped<IMongoDatabase>(provider => { 
    var settings = provider.GetService<IOptions<DbSettings>>(); 
    var client = new MongoClient(settings.Value.ConnectionString); 
    return client.GetDatabase(settings.Value.Database); 
}); 
services.AddScoped<IDbContext, DbContext>(); 
services.AddScoped<ILogItemRepository, LogItemRepository>(); 
//...NOTE: Use the desired service lifetime. This is just an example 

public class LogItemRepository : ILogItemRepository { 
    private readonly IDbContext context = null; 

    public LogItemRepository(IDbContext context) { 
     this.context = context; 
    } 

    //...other code 
} 

全ての層が今切り離されているコンテキストの抽象化に明示的に依存すると、明示的として行われるために、より分離されたユニットテストを可能に、それらの依存関係が何であるかの状態に必要です。

+0

ありがとう@Nkosi - それは私によく見えます。そのアプローチで行くだろう。 –

関連する問題