私はJavascriptでバックボーンモデルをテスト駆動しています。そのため、ユーザーが[保存]ボタンをクリックすると、適切なPOSTリクエストがASP.NET MVCアプリケーションに送信されているはずです。これは、このモデルのための最終的な統合状試験(this.server
がFake server from Sinon.JSである)である:要求コンテンツからインスタンス化とアクション呼び出しを使用してMVCコントローラをテストするにはどうすればよいですか?
it('should properly formulate request to save data', function() {
this.model.data = [{ id: 1, type: 'type', value: 'value' }];
this.model.save();
expect(this.server.requests.length).toEqual(1);
expect(this.server.requests[0].method).toEqual('POST');
expect(this.server.requests[0].url).toEqual('MyController/SaveData');
expect(this.server.requests[0].requestHeaders['Content-Type'])
.toEqual('application/json;charset=utf-8');
expect(this.server.requests[0].requestBody)
.toEqual('[{"id":1,"type":"type","value":"value"}]');
});
は、今私は、コントローラをテストドライブしたいです。 SaveData
アクション(これは簡単です)を正しく実装していることを確認したいだけですが、リクエストボディからアクション引数へのマッピングとMVCルートからのマッピングが意味を成していることを確認したいと思います。
HttpContextBase
らconsortesとのユニットテストのコントローラに関する多くの質問を見つけた
:残念ながら、彼らはすべてのコントローラとコールをインスタンス化
- ASP.NET MVC unit test controller with HttpContext
- How to mock the Request on Controller in ASP.Net MVC?
アクションメソッドを手動で実行します。これは私にとっては不満です:私は、JSから出てくる(そして前述のユニットテストによって守られている)同じリクエストコンテンツが、ASP.NETアプリケーション側で正しく動作することを主張したいと思います。
私が現在持っているのは、動作させ問題を説明するための草案です。私はスタブとモックのためにRhino Mocksを使用しています。特に、dataWebService
はアサーションに使用したいモックです。私はテストのポイントが何であるかを明確にするためにそれを含めてきましたが、一般的に問題とは無関係です。私は、これがユニットテストの厳密な定義に一致し、どこかでないことを知って、今
[Test]
public void GivenNoData_WhenPostingData_ThenCallsWebServiceSaveData()
{
var httpContext = MockRepository.GenerateStub<HttpContextBase>();
var httpRequest = MockRepository.GenerateStub<HttpRequestBase>();
httpRequest
.Stub(hr => hr.Url)
.Return(new Uri("http://localhost/MyController/SaveData"));
httpRequest
.Stub(hr => hr.Headers)
.Return(new WebHeaderCollection()
{
{ "X-Requested-With", "XMLHttpRequest" },
{ "Content-Type", "application/json;charset=utf-8" }
});
httpRequest
.Stub(hr => hr.RequestType)
.Return("POST");
var requestBody = @"[{""id"":1,""type"":""type"",""value"":""value""}]";
httpRequest
.Stub(hr => hr.InputStream)
.Return(new MemoryStream(Encoding.UTF8.GetBytes(requestBody)));
httpContext.Stub(hc => hc.Request).Return(httpRequest);
// The problem starts here
// I want MVC to instantiate the controller based on the request
var controller = new MyController(dataWebService);
controller.ControllerContext
= new ControllerContext(httpContext, new System.Web.Routing.RouteData(), controller);
dataWebService.Expect(dws => dws.SaveData(Arg<Data>.Matches(/*...*/));
// Second part of the problem, I want MVC to invoke SaveData with arguments
// generated from request's body
controller.SaveData(/* arguments */);
dataWebService.VerifyAllExpectations();
}
:問題は、(コントローラのインスタンスとアクションの呼び出し)二重であり、次のコードのコメントで示されユニットテストとインテグレーションテストの間にあります。
しかし、まず、プロセス全体が上から下に向かってテストされていることを確信したいと思います。そして定義について心配します(おそらくコントローラを単体テストに分割し、ルーティングとコントローラの引数解析のための統合的なテスト)。
また、MVCが正しく動作すると仮定すると、自分のコード、特にSaveData
メソッドシグネチャとMVCルート構成だけをテストすることに注意してください。
問題ありません。それらは単なる提案です。その日の終わりには、あなたやチームや開発のためのよりよいアプローチが何であるかをまだ知っています:) – jtabuloc
テスト用にあなたのウェブアプリケーションをどのようにホストしていますか? – BartoszKP
すべてのコードが統合される専用のテストサーバーが必要です。 TFSをリポジトリとして使用した場合は、すべてのチェックイン(クライアントの環境のように実際に展開する)で、更新、セットアップ、データベースの移行などを行うテストサーバーを指すビルド定義を作成できます。彼らがどのようにそれを行うのかについてGITかSVNでは分かりませんが、それはTFSのためです。 – jtabuloc