使用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);
}

有什么方法可以模拟CreateResponse,而无需使用部分模拟或直接使用“ new HttpResponseMessage(...)”?


1
为什么要嘲笑CreateResponse?为什么不对返回的HttpResponseMessage ContentStatusCode属性断言设置了正确的值?
nemesv 2012年

3
如果我在单元测试中运行此方法,则将失败,除非未设置配置。
2012年

1
好吧,可耻的是我,我只是需要写this.Request.CreateResponse(HttpStatusCode.Accepted,createdProduct,GlobalConfiguration.Configuration)
ASA

Answers:


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在控制器上进行填充,否则on上的扩展方法Request将无法工作。您还必须HttpConfiguration在Request上进行设置,否则路由和管道的其他部分将无法正常运行。


是的,这也可能起作用,但是似乎Request.CreateResponse也起作用。
2012年

4
添加GlobalConfiguration.Configuration仍然使请求为空。设置请求对我来说很有效,但这并不是我的问题的终点,因为我的操作还调用了Url.Link,并且未定义路由名称。
foolshat 2012年


此调用之后设置ControllerContext 也会给我该错误,但仅限于WebApi 5.0.0。但是,如果我在Request 设置HttpConfiguration对象,它可以正常工作。
mikebridge

这很完美,但是我不明白为什么会这样。您能在答案中详细说明吗?
2014年

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;

摘自Peter Provost关于单元测试ASP.NET Web API的综合博客文章。


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

WebAPI 1此处使用VB存在类似问题。

我设法在这里混合了响应,以使它像这样简单地工作:

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());
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.