Request.CreateResponseによるASP.NET WebApiユニットテスト


147

私のApiControllerのユニットテストを記述しようとして、いくつかの問題に直面しました。Request.CreateResponseと呼ばれる優れた拡張メソッドがあり、応答の生成に役立ちます。

public HttpResponseMessage Post(Product product)
{
  var createdProduct = repo.Add(product);
  return this.Request.CreateResponse(HttpStatusCode.Created, createdProduct);
}

部分的なモックを使用せずに、または「新しいHttpResponseMessage(...)」を直接使用せずにCreateResponseをモックする方法はありますか?


1
なんでモックしたいのCreateResponse?返さHttpResponseMessage ContentれたStatusCodeプロパティと正しい値が設定されているプロパティをアサートしないのはなぜですか?
nemesv

3
ユニットテストからこのメソッドを実行すると、構成が設定されていないという例外で失敗します。
asa

1
わかりました。恥ずかしいです。これを書く必要がありました。Request.CreateResponse(HttpStatusCode.Accepted、createdProduct、GlobalConfiguration.Configuration)
asa

回答:


243

これを解決する別の方法は、次のことです。

controller.Request = new HttpRequestMessage();
controller.Request.Properties.Add(HttpPropertyKeys.HttpConfigurationKey, 
                                  new HttpConfiguration());

webapi 5.0にアップグレードする場合は、次のように変更する必要があります。

controller.Request = new HttpRequestMessage();
controller.Request.SetConfiguration(new HttpConfiguration());

これを行う必要がある理由はRequest、コントローラーにデータを入力する必要があるためですRequest。そうしないと、拡張メソッドが機能しません。またHttpConfiguration、リクエストにセットが必要です。そうしないとルーティングが行われ、パイプラインの他の部分が正しく機能しなくなります。


はい、それはうまくいくかもしれませんが、Request.CreateResponseもうまくいくようです。
asa

4
GlobalConfiguration.Configurationを追加しても、リクエストはnullのままになります。リクエストの設定は私にとってはうまくいきましたが、私のアクションもUrl.Linkを呼び出しており、ルート名が定義されていなかったため、これは私の問題の終わりではありませんでした。
12

ルート設定するためのヘルプstackoverflow.com/questions/11779311/...
foolshat

この呼び出しのにControllerContextを設定すると、そのエラーも発生しますが、WebApi 5.0.0でのみ発生します。しかし、Request lastに HttpConfigurationオブジェクトを設定すると、正常に動作します。
mikebridge 2013年

これは完璧に機能しますが、なぜ機能するのか理解できません。答えでこれを詳しく説明してもらえますか?
Jan_V 14

24

次のように、テスト容易性のためにコントローラーオブジェクトを設定できます。

var config = new HttpConfiguration();
var request = new HttpRequestMessage(HttpMethod.Post, "http://localhost/api/products");
var route = config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}");
var routeData = new HttpRouteData(route, new HttpRouteValueDictionary { { "controller", "products" } });

controller.ControllerContext = new HttpControllerContext(config, routeData, request);
controller.Request = request;
controller.Request.Properties[HttpPropertyKeys.HttpConfigurationKey] = config;

ユニットテストASP.NET Web APIに関するPeter Provostの包括的なブログ投稿からコピーしました。


1
また、これに関連するMSのドキュメントに興味がある可能性があり:docs.microsoft.com/en-us/aspnet/web-api/overview/... ます。またSystem.Web.HttpとSystem.Netへの参照を追加する必要があるかもしれません。 Http
アーロンホフマン

4

Web API 2の場合、簡単に追加できます

controller.Request = new HttpRequestMessage();
controller.Configuration = new HttpConfiguration();

そのようです

[TestMethod]
public void GetReturnsProduct()
{
    // Arrange
    var controller = new ProductsController(repository);
    controller.Request = new HttpRequestMessage();
    controller.Configuration = new HttpConfiguration();

    // Act
    var response = controller.Get(10);

    // Assert
    Product product;
    Assert.IsTrue(response.TryGetContentValue<Product>(out product));
    Assert.AreEqual(10, product.Id);
}

コントローラでリクエストと構成を設定することが重要です。そうでない場合、テストはArgumentNullExceptionまたはInvalidOperationExceptionで失敗します。

詳細はこちらをご覧ください。


1

VBを使用した同様の問題があるWebAPI 1。

私はこれをここでハイブリッド化して、これを次のように単純に機能させることができました:

Dim request As HttpRequestMessage = New HttpRequestMessage()
Return request.CreateResponse(HttpStatusCode.BadRequest, myCustomClassObject, GlobalConfiguration.Configuration)

誰かを助けるために投稿するだけです。


0

テストクラスで、コントローラークラスのインスタンスを作成します。例えばvar customerController= new CustomerController();

customerController.Request = new HttpRequestMessage();
customerController.Request.Properties.Add(HttpPropertyKeys.HttpConfigurationKey, new HttpConfiguration());
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.