ASP.NET WebApi-Komponententest mit Request.CreateResponse

147

Ich versuche einige Unit-Tests für meinen ApiController zu schreiben und habe einige Probleme. Es gibt eine nette Erweiterungsmethode namens Request.CreateResponse, die beim Generieren von Antworten sehr hilfreich ist.

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

Gibt es eine Möglichkeit, CreateResponse zu verspotten, ohne Teilverspottungen zu verwenden oder "new HttpResponseMessage (...)" direkt zu verwenden?

Als ein
quelle
1
Warum willst du das verspotten CreateResponse? Warum nicht auf den zurückgegebenen HttpResponseMessage Contentund StatusCodeEigenschaften behaupten, dass die richtigen Werte eingestellt sind?
Nemesv
3
Wenn ich diese Methode für Komponententests ausführe, schlägt dies mit Ausnahme der fehlgeschlagenen Konfiguration fehl.
Asa
1
Ok, schade um mich, ich musste nur dies schreiben.Request.CreateResponse (HttpStatusCode.Accepted, createdProduct, GlobalConfiguration.Configuration)
als

Antworten:

243

Eine andere Möglichkeit, dies zu lösen, besteht darin, Folgendes zu tun:

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

Wenn Sie ein Upgrade auf Webapi 5.0 durchführen, müssen Sie dies ändern in:

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

Der Grund, warum Sie dies tun müssen, ist, dass Sie Requestauf dem Controller ausgefüllt haben müssen , sonst Requestfunktionieren die Erweiterungsmethoden nicht. Sie müssen auch einen HttpConfigurationSatz für die Anforderung haben, da sonst das Routing und andere Teile der Pipeline nicht richtig funktionieren.

jonnii
quelle
Ja, das könnte auch funktionieren, aber es scheint, dass Request.CreateResponse auch funktioniert.
Asa
4
Beim Hinzufügen von GlobalConfiguration.Configuration blieb die Anforderung weiterhin null. Das Festlegen der Anforderung funktionierte für mich, dies war jedoch nicht das Ende meiner Probleme, da meine Aktion auch Url.Link aufrief und der Routenname nicht definiert wurde.
Dummkopf
Hilfe zum Einrichten der Route stackoverflow.com/questions/11779311/…
Foolshat
Das Festlegen des ControllerContext nach diesem Aufruf gibt mir ebenfalls diesen Fehler, jedoch nur mit WebApi 5.0.0. Aber wenn ich das HttpConfiguration Objekt auf der Anfrage gesetzt zuletzt , es funktioniert gut.
Mikebridge
Das funktioniert perfekt, aber ich verstehe nicht, warum das funktioniert. Könnten Sie dies in der Antwort näher erläutern?
Jan_V
24

Sie können das Controller-Objekt für folgende Testbarkeit einrichten:

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;

Kopiert aus dem umfassenden Blog-Beitrag von Peter Provost über Unit Testing ASP.NET Web API .

mono68
quelle
1
Möglicherweise interessieren Sie sich auch für die diesbezüglichen MS-Dokumente: docs.microsoft.com/en-us/aspnet/web-api/overview/… Möglicherweise müssen Sie auch Verweise auf System.Web.Http und System.Net hinzufügen. Http
Aaron Hoffman
4

Für Web API 2 können Sie einfach hinzufügen

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

Wie so

[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);
}

Es ist wichtig, Anforderung und Konfiguration auf dem Controller festzulegen. Andernfalls schlägt der Test mit einer ArgumentNullException oder InvalidOperationException fehl.

Sehen Sie hier für weitere Informationen.

Dan Friedman
quelle
1

WebAPI 1 hier mit einem ähnlichen Problem mit VB.

Ich habe es geschafft, die Antworten hier zu kombinieren, damit dies so einfach funktioniert:

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

Nur posten, falls es jemandem hilft.

Rudy Scoggins
quelle
0

Erstellen Sie in Ihrer Testklasse eine Instanz der Controller-Klasse. z.Bvar customerController= new CustomerController();

customerController.Request = new HttpRequestMessage();
customerController.Request.Properties.Add(HttpPropertyKeys.HttpConfigurationKey, new HttpConfiguration());
Kiran Chaudhari
quelle