A-S*_*ani 5 c# unit-testing mocking asp.net-web-api
在我的Web API中,POST操作方法在服务器上上传文件.
对于单元测试此方法,我需要创建一个HttpContext并将一个文件放在其请求中:
HttpContext.Current.Request.Files
Run Code Online (Sandbox Code Playgroud)
到目前为止,我正在使用此代码伪装HttpContext,它完美地运行:
HttpRequest request = new HttpRequest("", "http://localhost/", "");
HttpResponse response = new HttpResponse(new StringWriter());
HttpContext.Current = new HttpContext(request, response);
Run Code Online (Sandbox Code Playgroud)
请注意,我不想使用Moq或任何其他Mocking库.
我怎么能做到这一点?(多部分内容可能吗?)
谢谢
由于大多数基础设施隐藏在密封或内部类中,我最终能够HttpContext通过大量使用反射来为WebApi单元测试添加假文件Request.Files.
添加下面的代码后,可以相对轻松地将文件添加到HttpContext.Current:
var request = new HttpRequest(null, "http://tempuri.org", null);
AddFileToRequest(request, "File", "img/jpg", new byte[] {1,2,3,4,5});
HttpContext.Current = new HttpContext(
request,
new HttpResponse(new StringWriter());
Run Code Online (Sandbox Code Playgroud)
随着繁重的工作完成:
static void AddFileToRequest(
HttpRequest request, string fileName, string contentType, byte[] bytes)
{
var fileSize = bytes.Length;
// Because these are internal classes, we can't even reference their types here
var uploadedContent = ReflectionHelpers.Construct(typeof (HttpPostedFile).Assembly,
"System.Web.HttpRawUploadedContent", fileSize, fileSize);
uploadedContent.InvokeMethod("AddBytes", bytes, 0, fileSize);
uploadedContent.InvokeMethod("DoneAddingBytes");
var inputStream = Construct(typeof (HttpPostedFile).Assembly,
"System.Web.HttpInputStream", uploadedContent, 0, fileSize);
var postedFile = Construct<HttpPostedFile>(fileName,
contentType, inputStream);
// Accessing request.Files creates an empty collection
request.Files.InvokeMethod("AddFile", fileName, postedFile);
}
public static object Construct(Assembly assembly, string typeFqn, params object[] args)
{
var theType = assembly.GetType(typeFqn);
return theType
.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null,
args.Select(a => a.GetType()).ToArray(), null)
.Invoke(args);
}
public static T Construct<T>(params object[] args) where T : class
{
return Activator.CreateInstance(
typeof(T),
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
null, args, null) as T;
}
public static object InvokeMethod(this object o, string methodName,
params object[] args)
{
var mi = o.GetType().GetMethod(methodName,
BindingFlags.NonPublic | BindingFlags.Instance);
if (mi == null) throw new ArgumentOutOfRangeException("methodName",
string.Format("Method {0} not found", methodName));
return mi.Invoke(o, args);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4981 次 |
| 最近记录: |