ASP.NET WebApi unit testing con Request.CreateResponse


147

Sto cercando di scrivere alcuni test unitari per il mio ApiController e ho riscontrato alcuni problemi. C'è un bel metodo di estensione chiamato Request.CreateResponse che aiuta molto nella generazione della risposta.

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

Esiste un modo per deridere CreateResponse senza l'utilizzo di simulazioni parziali o l'utilizzo diretto di "new HttpResponseMessage (...)"?


1
Perché vuoi deridere il CreateResponse? Perché non affermare sul reso HttpResponseMessage Contente sulle StatusCodeproprietà che sono impostati i valori corretti?
nemesv,

3
Se eseguo questo metodo da test unitari, fallirà con l'eccezione che la configurazione non è impostata.
asa

1
Ok, peccato per me, ho solo bisogno di scrivere questo. Richiesta.CreateResponse (HttpStatusCode.Accepted, creatoProduct, GlobalConfiguration.Configuration)
asa

Risposte:


243

Un altro modo per risolvere questo è quello di fare quanto segue:

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

Se stai aggiornando a webapi 5.0, dovrai cambiarlo in:

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

Il motivo per cui è necessario eseguire questa operazione è perché è necessario aver Requestpopolato il controller altrimenti i metodi di estensione su Requestnon funzioneranno. È inoltre necessario disporre di un HttpConfigurationset sulla richiesta, altrimenti il ​​routing e altre parti della pipeline non funzioneranno correttamente.


Sì, potrebbe anche funzionare, ma sembra che Request.CreateResponse funzioni anche.
asa

4
L'aggiunta di GlobalConfiguration.Configuration ha ancora lasciato la richiesta null. L'impostazione della richiesta ha funzionato per me, tuttavia questa non è stata la fine dei miei problemi in quanto la mia azione chiamava anche Url.Link e il nome della rotta non era definito.
sciocchi che il

Aiuto per l'impostazione di percorso stackoverflow.com/questions/11779311/...
foolshat

L'impostazione di ControllerContext dopo questa chiamata mi dà anche quell'errore, ma solo con WebApi 5.0.0. Ma se ho impostato l'oggetto HttpConfiguration sull'ultima richiesta , funziona benissimo.
mikebridge,

Funziona perfettamente, ma non riesco a capire perché funzioni. Potresti approfondire questo nella risposta?
Jan_V,

24

È possibile impostare l'oggetto controller per la testabilità in questo modo:

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;

Copiato dal post completo del blog di Peter Provost sull'API Web ASP.NET di Unit Testing .


1
Potresti anche essere interessato ai documenti MS relativi a questo: docs.microsoft.com/en-us/aspnet/web-api/overview/… Potrebbe anche essere necessario aggiungere riferimenti a System.Web.Http e System.Net. Http
Aaron Hoffman,

4

Per Web API 2, puoi semplicemente aggiungere

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

Così

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

È importante impostare Richiesta e configurazione sul controller. In caso contrario, il test avrà esito negativo con ArgumentNullException o InvalidOperationException.

Vedi qui per maggiori informazioni.


1

WebAPI 1 qui con un problema simile usando VB.

Sono riuscito a risposte ibride qui per farlo funzionare così semplice:

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

Basta pubblicare nel caso in cui aiuti chiunque.


0

Nella tua classe di test, crea un'istanza della classe controller. per esempiovar customerController= new CustomerController();

customerController.Request = new HttpRequestMessage();
customerController.Request.Properties.Add(HttpPropertyKeys.HttpConfigurationKey, new HttpConfiguration());
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.