使用Request.CreateResponse进行ASP.NET WebApi单元测试

asa*_*asa 144 c# unit-testing mocking httpresponse asp.net-web-api

我正在尝试为我的ApiController编写一些单元测试并遇到一些问题.有一个很好的扩展方法叫做Request.CreateResponse,可以帮助生成响应.

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

有没有办法在不使用部分模拟或直接使用"new HttpResponseMessage(...)"的情况下模拟CreateResponse?

jon*_*nii 238

解决此问题的另一种方法是执行以下操作:

controller.Request = new HttpRequestMessage();
controller.Request.Properties.Add(HttpPropertyKeys.HttpConfigurationKey, 
                                  new HttpConfiguration());
Run Code Online (Sandbox Code Playgroud)

如果要升级到webapi 5.0,则需要将其更改为:

controller.Request = new HttpRequestMessage();
controller.Request.SetConfiguration(new HttpConfiguration());
Run Code Online (Sandbox Code Playgroud)

您需要这样做的原因是您必须Request在控制器上填充,否则扩展方法Request将无效.您还必须HttpConfiguration在请求上设置一个集,否则路由和管道的其他部分将无法正常运行.

  • 添加GlobalConfiguration.Configuration仍然会将请求保留为null.设置请求对我有用,但这不是我的问题的结束,因为我的Action也在调用Url.Link并且未定义路由名称. (4认同)

mon*_*o68 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;
Run Code Online (Sandbox Code Playgroud)

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


Dan*_*man 6

对于 Web API 2,您只需添加

controller.Request = new HttpRequestMessage();
controller.Configuration = new HttpConfiguration();
Run Code Online (Sandbox Code Playgroud)

像这样

[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);
}
Run Code Online (Sandbox Code Playgroud)

在控制器上设置请求和配置很重要。否则,测试将因 ArgumentNullException 或 InvalidOperationException 而失败。

请参阅此处了解更多信息。