Teste de unidade ASP.NET WebApi com Request.CreateResponse


147

Estou tentando escrever alguns testes de unidade para o meu ApiController e enfrentou alguns problemas. Existe um bom método de extensão chamado Request.CreateResponse que ajuda muito na geração de resposta.

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

Existe alguma maneira de zombar do CreateResponse sem usar zombarias parciais ou usar diretamente o "novo HttpResponseMessage (...)"?


1
Por que você quer zombar do CreateResponse? Por que não afirmar nas propriedades HttpResponseMessage Contente retornados StatusCodeque os valores corretos estão definidos?
Nemesv

3
Se eu executar este método de testes de unidade, ele falhará, com exceção de que a configuração não está definida.
asa

1
Ok, vergonha em mim, eu só precisava para escrever this.Request.CreateResponse (HttpStatusCode.Accepted, createdProduct, GlobalConfiguration.Configuration)
asa

Respostas:


243

Outra maneira de resolver isso é fazer o seguinte:

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

Se você estiver atualizando para o webapi 5.0, precisará alterar isso para:

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

A razão pela qual você precisa fazer isso é porque você deve ter Requestpreenchido o controlador, caso contrário, os métodos de extensão Requestnão funcionarão. Você também deve ter um HttpConfigurationconjunto no Pedido, caso contrário, o roteamento e outras partes do pipeline não funcionarão corretamente.


Sim, isso também pode funcionar, mas parece que Request.CreateResponse também funciona.
asa

4
A adição de GlobalConfiguration.Configuration ainda deixou a solicitação nula. Definir a solicitação funcionou para mim, no entanto, esse não foi o fim dos meus problemas, pois minha ação também chamava Url.Link e o nome da rota não foi definido.
foolshat

Ajuda para configurar a rota stackoverflow.com/questions/11779311/…
foolshat

Definir o ControllerContext após esta chamada também me dá esse erro, mas apenas com o WebApi 5.0.0. Mas se eu definir o objeto HttpConfiguration no último pedido , ele funcionará bem.
Mikebridge # 28/13

Isso funciona perfeitamente, mas não entendo por que isso funciona. Você poderia elaborar isso na resposta?
Jan_V

24

Você pode configurar o objeto do controlador para testabilidade como este:

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;

Copiado da abrangente postagem de blog de Peter Provost na Unit Testing ASP.NET Web API .


1
Você também pode estar interessado nos documentos da Microsoft relacionados a isso: docs.microsoft.com/en-us/aspnet/web-api/overview/… Também pode ser necessário adicionar referências ao System.Web.Http e System.Net. Http
Aaron Hoffman

4

Para a API da Web 2, você pode simplesmente adicionar

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

Igual a

[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 definir Solicitação e Configuração no controlador. Caso contrário, o teste falhará com ArgumentNullException ou InvalidOperationException.

Veja aqui para mais informações.


1

WebAPI 1 aqui com um problema semelhante usando o VB.

Eu consegui respostas híbridas aqui para que isso funcionasse tão simples quanto isto:

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

Apenas postando caso ajude alguém.


0

Na sua classe de teste, crie uma instância da classe do controlador. por exemplovar customerController= new CustomerController();

customerController.Request = new HttpRequestMessage();
customerController.Request.Properties.Add(HttpPropertyKeys.HttpConfigurationKey, new HttpConfiguration());
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.