【问题标题】:Unit Test ASP.NET Web API controller with fake HTTPContext使用伪造的 HTTPContext 对 ASP.NET Web API 控制器进行单元测试
【发布时间】:2014-01-11 21:54:04
【问题描述】:

我正在使用以下方法通过 ASP.NET Web API 控制器上传文件。

[System.Web.Http.HttpPost]
public HttpResponseMessage UploadFile()
{
    HttpResponseMessage response;

    try
    {
        int id = 0;
        int? qId = null;
        if (int.TryParse(HttpContext.Current.Request.Form["id"], out id))
        {
            qId = id;
        }

        var file = HttpContext.Current.Request.Files[0];

        int filePursuitId = bl.UploadFile(qId, file);
    }
    catch (Exception ex)
    {

    }

    return response;
}

在我的单元测试中,我在调用 UploadFile 操作之前手动创建了一个 HTTPContext 类:

var request = new HttpRequest("", "http://localhost", "");
var context = new HttpContext(request, new HttpResponse(new StringWriter()));
HttpContext.Current = context;

response = controller.UploadFile();

很遗憾,我无法将自定义值添加到 Form 集合,因为它是只读的。我也无法更改 Files 集合。

有没有办法在单元测试期间向RequestFormFiles 属性添加自定义值以添加所需的数据(id 和文件内容)?

【问题讨论】:

    标签: c# asp.net unit-testing asp.net-mvc-4


    【解决方案1】:

    既然你无法控制这些类,为什么不封装/抽象一个 do control 背后的功能

    IRequestService request;
    
    [HttpPost]
    public HttpResponseMessage UploadFile() {
        HttpResponseMessage response;
    
        try {
            int id = 0;
            int? qId = null;
            if (int.TryParse(request.GetFormValue("id"), out id)) {
                qId = id;
            }
    
            var file = request.GetFile(0);
    
            int filePursuitId = bl.UploadFile(qId, file);
        } catch (Exception ex) {
            //...
        }
    
        return response;
    }
    

    其中request 是您自定义的类型之一IRequestService

    public interface IRequestService {
        string GetFormValue(string key);
        HttpPostedFileBase GetFile(int index);
        //...other functionality you may need to abstract
    }
    

    并且可以像这样实现以注入到您的控制器中

    public class RequestService : IRequestService {
    
        public string GetFormValue(string key) {
            return HttpContext.Current.Request.Form[key];
        }
    
        public HttpPostedFileBase GetFile(int index) {
            return new HttpPostedFileWrapper(HttpContext.Current.Request.Files[index]);
        }
    }
    

    在你的单元测试中

    var requestMock = new Mock<IRequestService>();
    //you then setup the mock to return your fake data
    //...
    //and then inject it into your controller
    var controller = new MyController(requestMock.Object);
    //Act
    response = controller.UploadFile();
    

    【讨论】:

      【解决方案2】:

      改用Moq 之类的模拟框架。使用您需要的任何数据创建一个模拟 HttpRequestBase 和模拟 HttpContextBase 并将它们设置在控制器上。

      using Moq;
      using NUnit.Framework;
      using SharpTestsEx;
      
      namespace StackOverflowExample.Moq
      {
          public class MyController : Controller
          {
              public string UploadFile()
              {
                  return Request.Form["id"];
              }
          }
      
          [TestFixture]
          public class WebApiTests
          {
              [Test]
              public void Should_return_form_data()
              {
                  //arrange
                  var formData = new NameValueCollection {{"id", "test"}};
                  var request = new Mock<HttpRequestBase>();
                  request.SetupGet(r => r.Form).Returns(formData);
                  var context = new Mock<HttpContextBase>();
                  context.SetupGet(c => c.Request).Returns(request.Object);
      
                  var myController = new MyController();
                  myController.ControllerContext = new ControllerContext(context.Object, new RouteData(), myController);
      
                  //act
                  var result = myController.UploadFile();
      
                  //assert
                  result.Should().Be.EqualTo(formData["id"]);
              }
          }
      }
      

      【讨论】:

      • 感谢您的回复。由于我们使用 web.api 控制器,我们需要使用 HttpControllerContext 而不是 ControllerContext。 HttpControllerContext 不允许传入构造函数 HttpContextBase。
      • 只是想知道为什么当 Pylyp Lebediev 说是真的时,为什么会被赞成......
      猜你喜欢
      • 1970-01-01
      • 2017-06-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-30
      • 1970-01-01
      相关资源
      最近更新 更多