![](/img/trans.png)
[英]How to unit test MVC controller that uses HttpContext in ASP.NET Core 1.1
[英]Unit Test ASP.NET Web API controller with fake HTTPContext
我正在使用以下方法通過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
集合。
有沒有辦法在單元測試期間向Request
的Form
和Files
屬性添加自定義值以添加所需數據(id和文件內容)?
使用一些像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"]);
}
}
}
由於您無法控制這些類,為什么不包裝/抽象一個控件后面的功能
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();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.