2013-05-14 10 views
5

私はリポジトリクラスからデータを取得するコントローラでテストをしようとしています。 これは私がテストしたいリポジトリの一部です:ユニットテストはMVC3のリポジトリクラスでどのように行うべきですか?

public class NewsRepository 
{ 
    public IEnumerable<NewsItem> GetNews() 
    { 
     var result = (from n in n_db.NewsItems 
        orderby n.ID descending 
        select n).Take(3); 
     return result; 
    } 
} 

テストがどのように機能するかを取得するだけでいくつかの小さなコード。 は私にHomeControllerに私はインデックス()の内部でこのコードを持っている:

public ActionResult Index() 
    { 
     ViewBag.Message = "Announcements"; 
     NewsRepository n_rep = new NewsRepository(); 
     var model = i_rep.GetNews(); 

     return View(model); 
    } 

私はすべての説明は素晴らしいことだテストに完全に新しいです。おかげさまで

答えて

8

それは強く次の行上のリポジトリに結合されているので、お使いのコントローラが孤立してテストしたユニットであることは不可能である。

NewsRepository n_rep = new NewsRepository(); 

あなたは単に、リポジトリの特定の実装をハードコーディングし、あなたのユニットテストあなたの中にいますそれを嘲笑することはできません。これを行うために、適切にあなたがこのリポジトリ上の抽象化を定義することによって開始する必要があります:

public interface INewsRepository 
{ 
    IEnumerable<NewsItem> GetNews(); 
} 

してから特定のリポジトリは、このインタフェースを実装する必要があり:

public class NewsRepository : INewsRepository 
{ 
    ... 
} 

[OK]を、今、我々はのは弱め抽象化を聞かせていることこの抽象化を使用して、データアクセスおよびコントローラロジック間の結合:

public class NewsController: Controller 
{ 
    private readonly INewsRepository repository; 
    public NewsController(INewsRepository repository) 
    { 
     this.repository = repository; 
    } 

    public ActionResult Index() 
    { 
     ViewBag.Message = "Announcements"; 
     var model = this.repository.GetNews(); 
     return View(model); 
    }  
} 

さてさて、今あなたがしっかりしなくなっているコントローラを持っていますいくつかの特定の実装と相まって、あなたはお気に入りのモックフレームワークをピックアップし、単体テストを書くことができます。

[TestMethod] 
public void Index_Action_Fetches_Model_From_Repo() 
{ 
    // arrange 
    var repo = Substitute.For<INewsRepository>(); 
    IEnumerable<NewsItem> expectedNews = new[] { new NewsItem() }; 
    repo.GetNews().Returns(expectedNews); 
    var sut = new NewsController(repo); 

    // act 
    var actual = sut.Index(); 

    // assert 
    Assert.IsInstanceOfType(actual, typeof(ViewResult)); 
    var viewResult = actual as ViewResult; 
    Assert.AreEqual(expectedNews, viewResult.Model); 
} 

そして、それはかなりそれだ:NSubstituteと例えばここにindexアクションのためのユニットテストは、次のようになります方法です。あなたのコントローラは単体で簡単にユニットテスト可能です。あなたはデータベースなどを設定する必要はありません。コントローラーのロジックをテストするのはそれがポイントではありません。

+0

これは、私が探している解決策ではない理由がわかりませんが、私はこれらのエラーを受け取ります:1. Public NewsController(INewsRepository repository)でエラー:不整合アクセシビリティ:パラメータタイプ 'TestProject.Models.INewsRepository'は、メソッド 'TestProject.Controllers.NewsController.NewsController(TestProject.Models.INewsRepository)'よりアクセスしにくいです。 ---- 2.行内:var repo = Substitute.For < INewsRepository>();エラー:名前 'Substitute'は現在のコンテキストに存在しません。 ----いくつかの名前空間がありますか? – Mappan

+0

代理人、リンクを確認するのを忘れました。しかし、最初のエラーが起きます。 – Mappan

+0

私の答えに示されているように、すべてのクラスとインタフェースは 'public'である必要があります。 NSubstituteに関するあなたのエラーに関する限り、NSubstitute NuGetをユニットテストプロジェクトにインストールする必要があります。 –

関連する問題