2009-12-01 12 views
23

NHibernate、ASP.NET MVC 2.0、StructureMapで新しいプロジェクトを開始し、テストにNUnitとMoqを使用しています。私のコントローラのそれぞれに対して、私は、単一のpublicコンストラクタを持ち、そこには、セッションが注入されています。アプリケーション自体はうまく動作しますが、単体テストの観点からは、コントローラをテストするためには基本的にセッションをモックする必要があります。MoqでNHibernateのセッションをモック

私はMOQでISessionをモックしようとすると、私は次のエラーメッセージを取得:

のみプロパティアクセスは、中間の呼び出しで

をサポートしている私の問題は、一覧を期待していることが表示されますフレームワークのCreateQueryメソッドからのユーザーが、私は今明確になっている問題をグーグルで調べています。

は、私は2つの質問があります:それは成功した私のリストを返すことができるようにコードを変更する方法を

1)これはISession

2)の依存性注入を模擬するために間違った方法ですがあります

  [Test] 
      public void DummyTest() 
      { 

       var mock = new Mock<ISession>(); 
       var loc = new Mock<User>(); 
       loc.SetupGet(x => x.ID).Returns(2); 
       loc.SetupGet(x => x.FirstName).Returns("John"); 
       loc.SetupGet(x => x.LastName).Returns("Peterson"); 

       var lst = new List<User> {loc.Object}; 
       mock.Setup(framework => framework.CreateQuery("from User").List<User>()).Returns(lst); 

       var controller = new UsersController(mock.Object); 
       var result = controller.Index() as ViewResult; 
       Assert.IsNotNull(result.ViewData); 
      } 

は私がちょうど(個々のユーザーをからかうと、リストに追加するのではなく)、ユーザーのハードコーディングされたリストを作成することができますかなり確信している、注意してくださいしかし、私はそれを持っているように、私は、コードを残したい考え出してください。たった今。

また、この特定のコントローラーのインデックスアクションは、基本的に上記のような模倣されたCreateQuery呼び出しを実行して、データベース内のすべてのユーザーを戻します。これは人為的な例です。詳細に何も読み込まないでください。あなたの助けを事前に

おかげ

編集:以下のコメントへの返信では、私はエラーのスタックトレースを追加しています。また、Userクラスのすべてのプロパティは仮想です。

のTestCase 'Beta.Tests.Unit.Controllers.UserControllerTest.Details_InValidIndex_ReturnsNotFoundView' に失敗しました:System.NotSupportedException: のみプロパティアクセスは 設定に中間の呼び出しで をサポートしています。サポートされない式 framework.CreateQuery( "ユーザーから")。 Moq.ExpressionVisitor.VisitでMoq.Mock.AutoMockPropertiesVisitor.VisitMethodCallで Moq.ExpressionVisitor.Visit(式 EXP)で Moq.Mock.AutoMockPropertiesVisitor.VisitMethodCall(MethodCallExpression M)(MethodCallExpression M)で (式 Moq.Mockで Moq.Mock.GetInterceptor(LambdaExpression ラムダ、モックモック)で Moq.Mock.AutoMockPropertiesVisitor.SetupMocks(式 式)で EXP)。 Moq.Mock.Setup [T1、TResult]で<> c__DisplayClass12 機能)(モックモック、 式1 expression) at Moq.Mock 1.Setup [TResult(Expression`1 式) コントローラ\ UserControllerTest。CS(29.0): Beta.Tests.Unit.Controllers.UserControllerTest.Details_InValidIndex_ReturnsNotFoundView()

+0

エラーのスタックトレースを表示できますか?ユーザープロパティは抽象的か仮想的か? –

答えて

20

以下は、私が思いついた解決策です。完全に機能するようです。再び、私はNHibernateをテストしていないので、私はデータベースをテストしていません - NHibernateに依存するコントローラをテストしたいだけです。最初の解決策の問題は、私がメソッドを呼び出していたことと、MOQセットアップ呼び出しでセッションのListメンバーを読み取っていたことにあります。私は、これらの呼び出しを、QueryMockとSession Mock(作成クエリはIQueryオブジェクトを返す)に分割して分割しました。トランザクションモックは

 [Test] 
     public void DummyTest() 
     { 
      var userList = new List<User>() { new User() { ID = 2, FirstName = "John", LastName = "Peterson" } }; 
      var sessionMock = new Mock<ISession>(); 
      var queryMock = new Mock<IQuery>(); 
      var transactionMock = new Mock<ITransaction>(); 

      sessionMock.SetupGet(x => x.Transaction).Returns(transactionMock.Object); 
      sessionMock.Setup(session => session.CreateQuery("from User")).Returns(queryMock.Object); 
      queryMock.Setup(x => x.List<User>()).Returns(userList); 

      var controller = new UsersController(sessionMock.Object); 
      var result = controller.Index() as ViewResult; 
      Assert.IsNotNull(result.ViewData); 
     } 
18

ではむしろSessionをからかっよりも、1ユニット・テストのために異なるConfigurationの設定を検討することがあります。このユニットテストConfigurationは、SQLiteやFirebirdのような高速のインプロセスデータベースを使用します。フィクスチャセットアップでは、最初から完全に新しいテストデータベースを作成し、スクリプトを実行してテーブルを設定し、初期レコードのセットを作成します。テストごとの設定では、トランザクションを開き、ポストテストティアダウンでトランザクションをロールバックして、データベースを以前の状態に復元します。ある意味では、Sessionを嘲笑しているわけではありません。なぜなら、それは難解ですが、実際のデータベースを嘲笑しているからです。

+0

ありがとうジャスティス。私は間違いなくそのことを考えていました。もしこのことができなければ、私の行く道になるでしょう。しかし、私はこのテストプロジェクトでデータベース全体を避けようとしています。もし私がNHibernateを模倣することができれば、私は私のテストをはるかに支配するだろうと思う...しかし、提案に感謝! –

+3

残念ながら、NHibernate 'Session'は、関連するオブジェクト、遅延ロード、キャッシング、およびNHibernateが行う他のすべてのことに関しては非常に複雑です。だから私はそれを模倣しようとするのをスキップし、代わりにデータベースを模擬しようとします。 Hibernateがあなたのマッピングから特定のデータベースシステム用のスキーマ作成スクリプトを生成し、そのスクリプトを実行してfixture-setupでスキーマを持つ空のデータベースを作成するのは簡単です。私のNHibernateでの経験や、Railsのようなフレームワークの観察から、これは本質的に唯一の方法です。 – yfeldblum

+0

ええ、あなたは正しいです...それはとてもうまくいくかもしれません。嘲笑されたDBを使う必要はありません。私たちのリレーショナルモデルをオブジェクトモデルに変換するnhibernateをすでに持っていれば、それはテストするのが奇妙です私たちはそれを直接テストすることができるはずです... 素敵な質問と回答、歓声:) – Marko

3

Ayendeから非常に良い記事がありますが、あなたがテストすることができますどのように...また、NHibernateのは、セッションの(私の場合)依存性があるとして必要だった:

http://ayende.com/Blog/archive/2009/04/28/nhibernate-unit-testing.aspx

歓迎

+0

良い記事:)しかし、他のコンポーネントをテストしたいときではなく、あなたのパーシスタンスロジックを本当にテストしたい場合には便利です。 – Beatles1692

関連する問題