单元测试WebForm的UI逻辑及文件上传

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

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)
  {
  }
}

 

Creative Commons License本文基于 Creative Commons Attribution 2.5 China Mainland License发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名 http://www.cnblogs.com/luminji(包含链接)。如您有任何疑问或者授权方面的协商,请给我留言。
目录
相关文章
|
10天前
|
开发框架 人工智能 小程序
小程序常见的 UI 框架
【10月更文挑战第17天】小程序 UI 框架为开发者提供了便捷的工具和资源,帮助他们快速构建高质量的小程序界面。在选择框架时,需要综合考虑各种因素,以找到最适合项目的解决方案。随着技术的不断进步,UI 框架也将不断发展和创新,为小程序开发带来更多的便利和可能性。
19 2
|
2月前
|
小程序 JavaScript 前端开发
小程序常见的UI框架
小程序常见的UI框架
282 60
|
2月前
|
开发框架 Android开发 iOS开发
Flutte之UI编写总结
Flutte之UI编写总结
|
4月前
|
开发框架 JSON 前端开发
基于ABP框架的SignalR,使用Winform程序进行功能测试
基于ABP框架的SignalR,使用Winform程序进行功能测试
以前编写好能够正常运行的 SAP UI5 代码,几个月后忽然不能运行了该怎么办?
以前编写好能够正常运行的 SAP UI5 代码,几个月后忽然不能运行了该怎么办?
|
测试技术 PHP
在Yii2框架下使用自带codeception进行单元测试提示model类不存在解决方法
在Yii2框架下使用自带codeception进行单元测试提示model类不存在解决方法
312 0
在Yii2框架下使用自带codeception进行单元测试提示model类不存在解决方法
|
Java 测试技术 开发工具
SAP ui5 单元测试框架 - OPA
Sent: Monday, July 4, 2016 6:41 PM
119 0
SAP ui5 单元测试框架 - OPA
|
测试技术 开发者
文件上传的单元测试怎么写?
文件上传的单元测试怎么写?
392 0
|
小程序
小程序UI框架minui
市面上小程序的UI框架似乎很少,不过合理的使用UI框架确实能帮助我们节省一些时间。同时考虑到知乎上评价minui与wepy的兼容性相对比较好,所以使用wepy的小伙伴可以了解一下。
2354 0
|
JavaScript 前端开发 测试技术