Testowanie jednostkowe ASP.NET WebApi z Request.CreateResponse

147

Próbuję napisać kilka testów jednostkowych dla mojego ApiController i napotkałem pewne problemy. Istnieje fajna metoda rozszerzenia o nazwie Request.CreateResponse, która bardzo pomaga w generowaniu odpowiedzi.

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

Czy jest jakiś sposób na mockowanie CreateResponse bez używania częściowych mocków lub bezpośredniego używania "nowego HttpResponseMessage (...)"?

jak
źródło
1
Dlaczego chcesz kpić z CreateResponse? Dlaczego nie potwierdzić na zwróconych HttpResponseMessage Contenti StatusCodewłaściwościach, że są ustawione prawidłowe wartości?
nemesv
3
Jeśli uruchomię tę metodę z testów jednostkowych, zakończy się niepowodzeniem, z wyjątkiem tego, że konfiguracja nie jest ustawiona.
asa
1
Ok, szkoda mi, po prostu musiałem to napisać.Request.CreateResponse (HttpStatusCode.Accepted, createdProduct, GlobalConfiguration.Configuration)
asa

Odpowiedzi:

243

Innym sposobem rozwiązania tego problemu jest wykonanie następujących czynności:

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

Jeśli aktualizujesz do Webapi 5.0, musisz zmienić to na:

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

Powodem, dla którego musisz to zrobić, jest to, że musisz Requestwypełnić kontroler, w przeciwnym razie metody rozszerzające Requestnie będą działać. Musisz również mieć HttpConfigurationzestaw na żądanie, w przeciwnym razie routing i inne części potoku nie będą działać poprawnie.

jonnii
źródło
Tak, to również może działać, ale wygląda na to, że Request.CreateResponse również działa.
asa
4
Dodanie GlobalConfiguration.Configuration nadal pozostawiało żądanie zerowe. Ustawienie żądania zadziałało, ale to nie koniec moich problemów, ponieważ moja akcja również wywoływała Url.Link, a nazwa trasy nie została zdefiniowana.
foolshat
Pomoc dotycząca konfiguracji trasy stackoverflow.com/questions/11779311/ ...
foolshat
Ustawienie ControllerContext po tym wywołaniu również daje mi ten błąd, ale tylko w przypadku WebApi 5.0.0. Ale jeśli ustawię obiekt HttpConfiguration w Request jako ostatni , działa dobrze.
mikebridge
Działa to doskonale, ale nie rozumiem, dlaczego to działa. Czy mógłbyś rozwinąć to w odpowiedzi?
Jan_V
24

Możesz ustawić obiekt kontrolera na testowalność w następujący sposób:

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;

Skopiowano z obszernego wpisu w blogu Petera Provosta na temat testów jednostkowych ASP.NET Web API .

mono68
źródło
1
Możesz być także zainteresowany dokumentami MS związanymi z tym: docs.microsoft.com/en-us/aspnet/web-api/overview/… Może być również konieczne dodanie odwołań do System.Web.Http i System.Net. Http
Aaron Hoffman
4

W przypadku interfejsu API sieci Web 2 możesz po prostu dodać

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

Tak, tak

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

Ważne jest, aby ustawić żądanie i konfigurację na kontrolerze. W przeciwnym razie test zakończy się niepowodzeniem z ArgumentNullException lub InvalidOperationException.

Więcej informacji znajdziesz tutaj .

Dan Friedman
źródło
1

WebAPI 1 z podobnym problemem przy użyciu VB.

Udało mi się tutaj uzyskać hybrydowe odpowiedzi, aby to działało tak prosto, jak to:

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

Po prostu publikuj na wypadek, gdyby to komuś pomogło.

Rudy Scoggins
źródło
0

W swojej klasie testowej utwórz wystąpienie klasy kontrolera. na przykładvar customerController= new CustomerController();

customerController.Request = new HttpRequestMessage();
customerController.Request.Properties.Add(HttpPropertyKeys.HttpConfigurationKey, new HttpConfiguration());
Kiran Chaudhari
źródło