2011-10-24 3 views
2

私の単純なIndex() ActionMethodでは、User.Identityプロパティを参照しています。だから私はそれを嘲笑する必要があると思った。私は自分のASP.NET MVCコントローラをモックすると、私のActionMethodはビューを返しません。どうして?

私はHomeControllerモックをいくつか作成し、これを私の単体テストで使用します。これを行うと、ActionMethodはビューとしてnullを返します。モックされたコントローラを具体的なインスタンスに置き換えると(もちろん、User.Identityへの参照をコメントアウトすると)、正しいビューが返されます。

例えば、

// Arrange. 
var homeController = Mock<HomeController>(..); 
homeController.Setup(x => x.User).Returns(new GenericPrincipal(..)); 

// Act. 
var result = homeController.Index(); 

// Assert. 
Assert.IsNotNull(result); // This fails here. result is NULL. 

が、私はこれを行う(および任意のUser参照をコメントアウト)する場合、それが動作...

// Arrange. 
var homeController = new HomeController(..); 

// Act. 
var result = homeController.Index(); 

// Assert. 
Assert.IsNotNull(result); // Tick! 

これがなぜ任意のアイデア?

+1

あなたはどのモックライブラリを使用していますか? –

+0

また、具体的にここでテストしているものは何ですか?嘲笑ライブラリーが機能するかどうか –

+0

私はMoqを使用しています。私はビューに戻ってくるいくつかの結果をテストしています。私はmoqライブラリ自体をテストしていません。モックコントローラにはViewEngineに必要なコンテキストやリクエストがないため、この問題があると思いますか? –

答えて

2

は、ここでは、ユニットテストに喜んでいるコントローラに嘲笑ユーザーを注入するための正しい方法です。 I provided one on another answer that you could useSteve Rowbothamによれば、テスト中のシステム(つまりコントローラの依存関係)の依存関係を嘲笑し、テスト対象のシステム自体を嘲笑しないでください。あなたは単にあなたのテストでは、次の

var controllerToTest = new HomeController(); 
var context = new MockHttpContextBase(controllerToTest); 

// do stuff that you want to test e.g. something goes into session 

Assert.IsTrue(context.HttpContext.Session.Count > 0); 

をするだろうあなたはさらに一歩行くことが、コントローラではないモックの本当のバージョンをテストするために:)

リンクからHttpContextBaseクラスを使用したいとセットアップとTearDownメソッドを作成して、コントローラを虚偽のコンテキストで設定します。

1

正直言って、これはテスト対象システム(SUT)を嘲笑している、つまりHomeControllerだからこそ、非常に奇妙なテストのようです。通常、SUTの依存関係を擬似的に模擬し、模擬に対する期待値を設定し、模擬テストをSUTに挿入して、それがその依存関係と適切に相互作用していることを確認する。

HomeControllerのモックを作成すると、MoqはHomeControllerから継承するクラスを作成し、仮想メソッドIndexを上書きします。したがって、Indexをモックで呼び出すと、HomeControllerクラスで定義したオーバーライドされた実装であるIndexの実装を呼び出さないことになります。あなたが明示的にSetupのメソッドを使っていないので、この場合はnullというデフォルト値が返されます。

HomeControllerクラスの実際のインスタンスを構築しているため、2番目のテストではIndexという実際の実装を呼び出しています。モックオブジェクトのインスタンス上でGetType()を呼び出すと、HomeControllerから派生したプロキシのインスタンスであることがわかります。これは、基本クラスの公開されたオーバーライド可能なメソッドへの呼び出しを傍受します(目的の大部分です)。モックオブジェクトの)。

3

ユニットテストには奇妙なことがいくつかあります。あなたはコントローラをユニットテストしていますが、テスト中のオブジェクトの作成を嘲笑しています:var homeController = Mock<HomeController>(..);これは間違っています。私はあなたがで動作するように、コントローラ用のHttpContextをからかっされるべきだと思う

// arrange 
var sut = new HomeController(); 
var user = new GenericPrincipal(new GenericIdentity("foo"), null); 
var httpContext = new Mock<HttpContextBase>(); 
httpContext.Setup(x => x.User).Returns(user); 
var context = new ControllerContext(new RequestContext(httpContext.Object, new RouteData()), sut); 
sut.ControllerContext = context; 

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

// assert 
... 
+0

乾杯!私はこれを前にしておきます。さて、これは...どこかで見たコードを思い出させてくれる。 –

+1

@ Pure.Krome、[場所のざらつき](http://www.google.com/search?s?hl=en&sugexp=kjrmc&cp=35&gs_id=3l&xhr=t&q=moq%20asp.net%20mvc%20moq%) hp&pbx = 1&oq =&aq =&aqi =&aqi =&gs_sm =&gs_upl =&bav = on.2、または。このコードを見つけるインターネット上で、r_gc.r_pw。、cf.osb&biw = 1680&bih = 945&ech = 2&psi = K0ilTsrKCYTqOYLE6fwE.1319454763487.4&emsg = NCSR&noj = 1&ei = M0ilTue3J9CXOsfX_L4N)ここに例があります:http://www.codethinked.com/simplified-aspnet-mvc-controller-testing-with-moq –

+0

私は仕事を辞めた後、昨夜見つけました。それはNerdDinnerからだった - パート12:http://nerddinnerbook.s3.amazonaws.com/Part12.htm :) –

1

あなたのIndexメソッドはおそらく仮想であり、Moqはその機能を模擬関数で置き換えると思います。これを防ぐには、モックにCallBaseプロパティを設定する必要があります。

しかし、あなたのコントローラを嘲笑してはならないという他の回答に同意しますが、あなたはあなたの依存関係を模倣すべきです。

(より簡単な方法は、のHttpContextからプリンシパルを取得することができ、特殊なモデルバインダーを作成することで、その後、あなたは自分のメソッドへの入力パラメータとして校長を渡すことができます)

関連する問題