zoukankan      html  css  js  c++  java
  • 单元测试WebForm的UI逻辑及文件上传

    BS系统中的UI部分的逻辑测试,最首要的就是要模拟请求(Request)和输出(Response),而WebForm又跟MVC不一样,后者的Response,Request等HTTP上下文对象均有接口支持,很容易模拟,而查看WebForm的对应对象,如Response,我们首先看到的声明就是:

    public sealed class HttpResponse

    无接口,并且是sealed,换句话说,我们要测试一个如下的的Code-Behind函数的逻辑正确性,该怎么测试:

    protected void Page_Load(object sender, EvengArgs e)
    {
      this.Response.Write("test u");
    }

    好在FCL中有现成的包装类HttpResponseWrapper来解决我们的烦恼(不然得自己写包装类),我们将上面的代码改成如下的形式,它就可以变得可测试:

    protected HttpResponseBase _response;
    
    protected override void OnPreLoad(EventArgs e)
    {
      base.OnPreLoad(e);
      _response = new HttpResponseWrapper(this.Response);
    }
    
    protected void Page_Load(object sender, EvengArgs e)
    {
      _response.Write("test u");
    }

    上面的重构,并不影响原有功能的实现,同时却将代码修改成可测试的,

    1:首先,this.Response被替代成可以被模拟的HttpResponseBase;

    2:其次,方法Page_Load内部不再负责生成被依赖的对象的生成;

             即,我们将_response的生成放到方法的外部。这个外部,可以是构造器等,不过由于webform本身的特殊性,在构造器中,this.Response上下文还不可用,所以在这个例子中放到了OnPreLoad中。 

    接下来看看测试类的编写,先说点额外话,Page_Load是protected的,要让测试类可以访问到它,需改成public或者干脆让测试类继承我们的当前页面,这里采用的是后者:

    [TestClass]
    public class _DefaultTest: _Default        ////很明显,这里测试的是Default.aspx.cs这个类
    {
      public Mock<HttpResponseBase> FakeResponse;
    
      [TestMethod]
      public void LoadOk()
      {
    FakeResponse = new Mock<HttpResponse>();
    
    StringWriter sw = new StringWriter();
    FakeResponse.SetupGet(x=>x.OutPut).Returns(sw);
    this._response = FakeResponse.Object;
    
    FakeResponse.Setup(x=>x.Write(It.IsAny<string>())).CallBack<string((x)=>
    {
      sw.Write(x);
      sw.Flush();
    }
    
    this.Page_Load(null,null);
    Assert.AreEqual(
      “test u”,
      (FakeResponse.Object.Output as StringWriter).ToString();
      }
    }

    首先,这个测试方法要测试的是Page_Load方法的逻辑正确性,即:执行完毕,客户端输出“test u”,它所依赖的是Response.Write这个方法,这个方法是向客户端浏览器输出文本,显然我们的单元测试中是不允许网络传输的,所以我们只能将Response.Write这个行为模拟到内存中去,测试代码中很大一部分就是模拟这个行为。要深刻理会的是:

    1:我们要验证的是Page_Load行为的准确性,而不是验证Response.Write的准确性;

    2:Response.Write是Page_Load行为中的一种依赖,测试方法要对这种依赖进行模拟;

    备注:Response.Write内部使用TextWriter,模拟的时候,我们使用了TextWriter的一个子类,StringWriter。 

    上面的例子很简单,进一步看,我们如何来写针对文件上传的单元测试。假设上传的逻辑是这样的:

    Public void UploadFile()
    {
      Var file = _request.Files[0];
      If(file.contentLength==0 || file.ContentLength > 5 * 1024 * 1024)
      {
    throw new ArgumentException();
      }
      File.SaveAs(file.FileName);
    }

    则,其中一个测试用例的代码应该象如下这样:

    [TestMethod]
    public void ThrowExceptionIfFilelengthInvalid()
    {
      FakeRequest = new Mock<HttpRequestBase>();
      FakeFiles = new Mock<HttpFileCollectionBase>();
      FakeFile = new Mock<HttpPostedFileBase>();
    
      FakeFile.SetupGet(x=> x.ContentLength).Returns(6 * 1024 * 1024);
      FakeFiles.SetupGet( x=> x[0]).Returns(FakeFile.Object);
      FakeRequest.SetupGet( x=>x.Files).Returns(FakeFiles.Object);
    
      this._request = FakeRequest.Object;
    
      try
      {
    this.UploadFile();
    Assert.Fail();
      }
      catch(ArugmentOutOfRangeException)
      {
      }
    }
  • 相关阅读:
    SQL union用法转载自http://www.cnblogs.com/johngong/archive/2008/04/25/1170519.html
    jquery ajax调用后台方法返回json数据转自http://www.cnblogs.com/xiaoxi/archive/2011/03/31/2000803.html
    我所知道的CallbackContract in WCF
    我所知道的CallbackContract in WCF
    使用Web.Config Transformation配置灵活的配置文件
    InfluxDB基本概念和操作
    ContentControl 的使用
    jsp_servlet时序图
    insertAdjacentHTML和insertAdjacentText方法(转)
    在Javascript中Eval函数的使用(转)
  • 原文地址:https://www.cnblogs.com/luminji/p/2796032.html
Copyright © 2011-2022 走看看