.ashx接口单元测试

      最近项目中需要修改一个文件上传的.ashx处理,代码的大概形式是这样的:

public void ProcessRequest(HttpContext context)

{

   CallA(context);

}

     方法CallA中直接使用了context并做了很多业务判断,也没有时间重构此方法,因此想对修改的代码做单元测试,

就需要Mock或实例化context参数。
     提示:我们开发环境为vs2010,mock组件为moq,当然有条件使用moles或是mvc的情况下,做这个单元测试还是比较容易的

     由于HttpContext是密封类,Moq就显得无力了,那就只有自己实例化了,从网上发现了有个帮助类,心中暗喜

https://svn.re-motion.org/svn/Remotion/branches/1.8/Web/UnitTests/AspNetFramework/HttpContextHelper.cs

在此感谢作者的无私的贡献。直到使用后发现一个问题,这个帮助类只支持对querystring,form,session的赋值,

而项目中却需要对context.Request.ServerVariables和context.Request.Files赋值(文件上传嘛,你懂的),

于是作为码农的我就开始堆代码了

下面是设置服务端参数的函数的实现:

        public static void SetServerVar(HttpContext context, NameValueCollection vars)

        {

            System.Collections.Hashtable hash = new System.Collections.Hashtable();



            Type entryType = typeof(System.Collections.Specialized.NameObjectCollectionBase).GetMethod("FindEntry", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).ReturnType;

            Type p = typeof(System.Web.HttpApplication).Assembly.GetType("System.Web.HttpServerVarsCollectionEntry");



            foreach (string key in vars)

            {

                var httpServerVarsCollectionEntry = PrivateInvoke.CreateInstanceNonPublicCtor(p, new object[] { key, vars[key] });



                var entry = PrivateInvoke.CreateInstanceNonPublicCtor(entryType, new object[] { key, httpServerVarsCollectionEntry });



                hash[key] = entry;

            }

            PrivateInvoke.SetNonPublicField(context.Request.ServerVariables, "_entriesTable", hash);

            PrivateInvoke.SetNonPublicField(context.Request.ServerVariables, "_allKeys", new string[] { "server_name" });

        }

下面是设置上传文件的代码:

        public static void SetFile(HttpContext context, string formName, string contentType, string fileName, byte[] file)

        {

            Type httpInputStream = typeof(HttpPostedFile).GetConstructors(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)[0].GetParameters()[2].ParameterType;



            Type httpRawUploadedContent = httpInputStream.GetConstructors(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)[0].GetParameters()[0].ParameterType;



            var row = PrivateInvoke.CreateInstanceNonPublicCtor(httpRawUploadedContent, new object[] { file.Length, file.Length });

            PrivateInvoke.SetNonPublicField(row, "_data", file);

            PrivateInvoke.SetNonPublicField(row, "_length", file.Length);

            PrivateInvoke.SetNonPublicField(row, "_completed", true);



            var stream = PrivateInvoke.CreateInstanceNonPublicCtor(httpInputStream, new object[] { row, 0, file.Length });



            HttpPostedFile f = (HttpPostedFile)PrivateInvoke.CreateInstanceNonPublicCtor(typeof(HttpPostedFile), new object[] { fileName, contentType, stream });



            PrivateInvoke.InvokeNonPublicMethod(context.Request.Files, "AddFile", new object[] { formName, f });

        }

代码我就不解释了,没什么技术含量。在此建议在写函数时尽量减少依赖性,如上面的CallA方法传入的是业务参数,也就没有这些问题了

最后,附上源码及demo,猛击我下载

 

你可能感兴趣的:(单元测试)