2016-07-13 11 views
1

私が作ったWebApiコントローラをテストしようとしています。依存性注入を使用してテストを容易にしようとしました。実際には反対の効果がありますが。ApiControllerを模擬しました

私は現在、そのコンストラクタでrepoインターフェイスを取るコントローラを持っています。 Repoインタフェースはコンストラクタ内でDbContextインタフェースも受け取ります。私はDbContextを擬似する必要があると思っているのでしょうか?レポを嘲笑し、その模擬レポを私がテストしているコントローラの実際の実装に渡すときに、その虚偽のコンテキストを引数として渡しましたか?

私はMoqとNUnitを使用しています。

ありがとうございました

+0

ここで、いくつかのコードサンプルを共有してください。コミュニティがあなたの正確なシナリオを理解し、より直接的な助けを得るのを助けます:)。 – davidallyoung

答えて

3

私はあなたがモックを利用しているので、ユニットテストについて話していると仮定しています。

あなたがテストしているクラスが依存している最初のレベルのインターフェイスよりも深く黙らせる必要はありません。あなたの例では、あなたのcontrollerは、インターフェイスに依存して、IRepositoryを呼び出します。あなたのの実装IRepositoryは、IDbContextになります。あなたがIRepositoryのインタフェースを嘲笑している限り、前の文の太字/斜体に注意してください。IDbContextはどのような関係もありません。IDbContextは具体的なリポジトリの依存関係ですが、IRepositoryは依存しません。

IRepositoryには、コントローラの単体テストに関連するデータ/ビヘイビアを模倣するためにコントローラが必要とするすべてのものが必要です。

例:テストMyControllerの目的のために

public class MyController : MyController 
{ 
    private readonly IRepository _repo; 

    public MyController(IRepository repo) 
    { 
     _repo = repo; 
    } 

    public IActionResult GetData(string userId) 
    { 
     var data = _repo.GetUserInformation(userId); 
     var someTransformation = null; // transform data 
     return View(someTransformation); 
    } 
} 

public interface IRepository 
{ 
    MyObject GetData(string userId); 
} 

public class Repository : IRepository 
{ 
    private readonly IDbContext _iDbContext; 

    public Repository(IDbContext iDbContext) 
    { 
     _iDbContext = iDbContext; 
    } 

    public MyObject GetUserInformation(string userId) 
    { 
     return _iDbContext.MyObjects.Where(w => w.UserId == userId); 
    } 
} 

public interface IDbContext 
{ 
    // impl 
} 

public class DbContext : IDbContext 
{ 
    // impl 
} 

、あなたはインターフェイスIRepositoryに依存しています。 IRepositoryRepository)の実装が依存するのは、MyControllerのテストの対象外ですあなたのテストで

:上記のテストで

public class MyControllerTests 
{ 
    public void MyTest() 
    { 
     Mock<IRepository> mockRepo = new Mock<IRepository>(); 
     mockRepo 
      .Setup(s => s.GetUserInformation(It.IsAny<string>()) 
      .Returns(new MyObject() 
      { 
       UserId = "whatever", // or whatever the mocked data needs to be 
       DateCreated = DateTime.MinValue 
      }); 
    } 
} 

、我々はGetUserInformationが呼び出されたときにIRepositoryが返すサンプルデータを提供している、我々はIRepositoryとして、でも実際DbContextに依存しない、またはIDbContext単に「GetUserInformationが文字列で呼び出されたときにMyObjectを返す」という契約を定義します。それをどうするかは問題ではありません。

+0

これは最高の答えです。ありがとう、あなたは正しかった、私が依存性注入を使用していたので、私は最初の層を模擬するだけでした。早速のご返事ありがとうございます。 – SwimmingG

1

あなたの直感を信頼してください。あなたのDbContextは、必要なものすべてにアクセスできるインターフェイスを実装していると想定しています。そのインターフェイスは、DI経由でコントローラのコンストラクタに渡すものです。

テストアセンブリで、インターフェイスを実装し、既知の模擬データを返すMockDbContextを作成します。次に、MockDbContextを使用してコントローラのインスタンスを作成し、コントローラに対してテストを実行します。

問題がある場合は、コメントを入力して回答を更新してください。

関連する問題