2011-01-29 12 views
2

が、私は私のコントローラをテストしてみてください失敗ここでASP.NET MVCコントローラユニットテストは

[TestMethod] 
    public void Index() 
    { 
     AdminController controller = new AdminController(); 
     ViewResult result = controller.Index() as ViewResult; 
     Assert.IsNotNull(result); 
    } 

ですIndex()コード:

public ActionResult Index() 
     { 
      var repository = new PostsRepository(); 
      var posts = repository.GetAllPosts(); 

      return View(posts); 
     } 

リポジトリ:

public class PostsRepository : IPostsRepository 
    { 
     PostsDataContext _dataContext = new PostsDataContext(); 

     public IQueryable<Post> GetAllPosts() 
     { 
      var posts = from t in _dataContext.Posts select t; 
      return posts; 
     } 

     public Post GetPostById(int id) 
     { 
      var post = from t in _dataContext.Posts 
         where t.id == id 
         select t; 
      return post.First(); 
     } 
    } 

しかし、私のIndex()のユニットテストエラーで失敗します。

Test method MvcBlog.Tests.Controllers.AdminControllerTest.Index threw exception: 
System.NullReferenceException: Object reference not set to an instance of an object. 

スタックトレース:

MvcBlog.Models.PostsDataContext..ctor() in C:\Users\cL1Nk3r\Documents\Visual Studio 2010\Projects\MvcBlog\MvcBlog\Models\Posts.designer.cs: line 38 
MvcBlog.Repository.PostsRepository..ctor() in C:\Users\cL1Nk3r\Documents\Visual Studio 2010\Projects\MvcBlog\MvcBlog\Repository\PostsRepository.cs: line 11 
MvcBlog.Controllers.AdminController.Index() in C:\Users\cL1Nk3r\Documents\Visual Studio 2010\Projects\MvcBlog\MvcBlog\Controllers\AdminController.cs: line 19 
MvcBlog.Tests.Controllers.AdminControllerTest.Index() in C:\Users\cL1Nk3r\Documents\Visual Studio 2010\Projects\MvcBlog\MvcBlog.Tests\Controllers\AdminControllerTest.cs: line 19 

、それは誤りであるのはなぜ?
私はちょうど私のアプリケーションを実行すると、それが正常に動作します。

ソースコードのダウンロード:

var repository = new PostsRepository(); 
ここ

あなたがユニットには非常に困難にリポジトリの特定の実装にあなたのコントローラを抱き合わせされていますhttp://dl.dropbox.com/u/14053604/MvcBlog.rar

+0

ソースコードを共有できますか?なぜDataContextが例外をスローするのか分かりません。ここで – Restuta

+0

:http://dl.dropbox.com/u/14053604/MvcBlog.rar – Sergey

答えて

6

問題は、あなたのコントローラのアクションに次の行があります孤立してテストする。お使いのコントローラとデータアクセス層との間に弱い結合を実現するためには、私はコンストラクタ・インジェクションを使用して、あなたをお勧めします:

public class PostsController: Controller 
{ 
    private readonly IPostsRepository _repository; 
    public PostsController(IPostsRepository repository) 
    { 
     _repository = repository; 
    } 

    public ActionResult Index() 
    { 
     var posts = _repository.GetAllPosts(); 
     return View(posts); 
    } 
} 

今、あなたのコントローラが完全などのデータベースに依存する場合がありますリポジトリの特定の実装から切り離され今、あなたはユニットテストのために、このリポジトリのダミー実装を提供するRhino MocksまたはMoqようなモックフレームワークを使用することができます。

個人的に私はRhinoのモックと連携し、コントローラのアクションの非常にエレガントなユニットテストを可能にするMVCContrib TestHelperとても好きです。したがって、私が示したように、コントローラをリポジトリの特定の実装から分離したら、次のユニットテストを行うことができます:

[TestMethod] 
public void PostsController_Index_Action_Should_Fetch_All_Posts_From_Repository() 
{ 
    // arrange 
    var postsRepositoryStub = MockRepository.GenerateStub<IPostsRepository>(); 
    var sut = new PostsController(postsRepositoryStub); 
    var expectedPosts = new Post[0]; 
    postsRepositoryStub.Stub(x => x.GetAllPosts).Return(expectedPosts); 

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

    // assert 
    actual 
     .AssertViewRendered() 
     .WithViewData<IEnumerable<Post>>() 
     .ShouldBe(expectedPosts); 
} 
+0

それは私のコードでは、コードは、エラーメッセージに記載されているという理由だけで、同じエラーを取得することは不可能である、同じエラー – Sergey

+0

@Sergeyです'PostsRepository'にあるユニットテストでは決して**実行されません。私は偽のリポジトリを使用します。 –

+0

しかし、アプリケーションを実行すると正しく動作するのはなぜですか? – Sergey