Unit Test ASP.NET Web API controller with fake HTTPContext

前端 未结 2 1511
抹茶落季
抹茶落季 2020-12-10 01:04

I\'m using the following approach to upload files through ASP.NET Web API controllers.

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


        
相关标签:
2条回答
  • 2020-12-10 01:27

    Since you have no control over those classes why not wrap/abstract the functionality behind one 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;
    }
    

    Where request is one of your custom defined types IRequestService

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

    and can be implemented like this to be injected into your controller

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

    in your unit test

    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();
    
    0 讨论(0)
  • 2020-12-10 01:30

    Use some mocking framework like Moq instead. Create a mock HttpRequestBase and mock HttpContextBase with whatever data you need and set them on the controller.

    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"]);
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题