汉广

常怀恭敬之心
随笔 - 16, 文章 - 0, 评论 - 134, 引用 - 2
数据加载中……

为Asp.net控件写单元测试(ViewState)

 

通常一个典型的asp.net控件至少会用ViewState存储一些属性,以便于在页面postback后不用重新设置。在这篇文章里我将介绍如何为控件写单元测试,以确保一个属性被正确的保存在ViewState里。

为了演示,我写了一个简单的控件。

namespace Eilon.Sample.Controls {
using System;
using System.Web.UI;
public class NewLabel : Control {
public string Text {
get {
string s = ViewState["Text"] as string;
return s ?? String.Empty;
}
set {
ViewState["Text"] = value;
}
}
protected override void Render(HtmlTextWriter writer) {
writer.Write(Text);
}
}
}

这个控件只是简单的将它唯一的属性Text输出。

好的,让我们写一个简单的单元测试,以确保这个控件正确的工作。

namespace Eilon.Sample.Controls.Test {
using System;
using System.IO;
using System.Web.UI;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class NewLabelTest {
[TestMethod]
public void TextReturnsEmptyStringDefault() {
NewLabel label = new NewLabel();
Assert.AreEqual<string>(String.Empty, label.Text,

"Default text should be empty string (not null)");
}
[TestMethod]
public void GetSetText() {
const string value = "Some Text";
NewLabel label = new NewLabel();
label.Text = value;
Assert.AreEqual<string>(value, label.Text,

"Property value isn't the same as what we set");
}
[TestMethod]
public void RenderEmpty() {
NewLabel label = new NewLabel();
Assert.AreEqual<string>(String.Empty, GetRenderedText(label),

"Shouldn't have rendered anything");
}
[TestMethod]
public void RenderWithText() {
const string value = "Some Text";
NewLabel label = new NewLabel();
label.Text = value;
Assert.AreEqual<string>(value, GetRenderedText(label),

"Should have rendered the text");
}
private static string GetRenderedText(Control c) {
HtmlTextWriter writer = new HtmlTextWriter(new StringWriter());
c.RenderControl(writer);
return writer.InnerWriter.ToString();
}
}
}

看上去我们已经覆盖了100%的代码,是这样吗?事实上我们根本不能保证这个控件的属性已经被正确的存储到ViewState里了。可是我们知道与ViewState有关的函数都是protected的,并不能从外部访问。解决这个问题,可以有很多办法,这里我们写一个internal interface

// Interface to expose protected methods from
// the Control class to our unit test
internal interface IControl {
void LoadViewState(object savedState);
object SaveViewState();
void TrackViewState();
}
然后让我们的控件去实现它:

#region IControl Members
void IControl.LoadViewState(object savedState) {
LoadViewState(savedState);
}
object IControl.SaveViewState() {
return SaveViewState();
}
void IControl.TrackViewState() {
TrackViewState();
}
#endregion

现在就可以测试ViewState了:

[TestMethod]
public void TextSavedInViewState() {
// Create the control, start tracking viewstate,
// then set a new Text value
const string firstValue = "Some Text";
const string secondValue = "ViewState Text";
NewLabel label = new NewLabel();
label.Text = firstValue;
((IControl)label).TrackViewState();
label.Text = secondValue;
// Save the control's state
object viewState = ((IControl)label).SaveViewState();
// Create a new control instance and load the state
// back into it, overriding any existing values
NewLabel newLabel = new NewLabel();
label.Text = firstValue;
((IControl)newLabel).LoadViewState(viewState);
Assert.AreEqual<string>(secondValue, newLabel.Text,
"Value restored from viewstate does not match the original value we set");
}

这里注意一点,我们的接口是internal的,为了让测试用例可以访问它,需要添加

using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("MyControlLibrary.Test")]

 

 

 

 

 

 

 

posted on 2007-06-05 11:51 汉广 阅读(2396) 评论(12)  编辑 收藏 所属分类: Asp.net

评论

#1楼    回复  引用  查看    

呵呵,代码工整,历害...
2007-06-05 20:28 | 沧海依粟      

#2楼 [楼主]   回复  引用  查看    

Eilon写的,Eilon是牛人啊,
你要是说那俩行文字工整就好了,:-)。
2007-06-05 21:12 | Osamede      

#3楼    回复  引用  查看    

思路严谨..表达清析..很有价值哦! 好好学习啰!呵呵~~
2007-06-05 23:28 | 明明MM      

#4楼    回复  引用    

呵呵,谢谢博主的好文章

您能不能写写用VS.NET2005来进行测试的系列文章呢,我觉得很多人虽然接触过VS.NET,但测试这方面有时候还有点空缺

只是建议而已,呵呵,还是谢谢您的文章
2007-06-06 09:23 | 书生 [未注册用户]

#5楼    回复  引用  查看    

今天才知道还可以这样对WEB控件进行单元测试
2007-06-06 10:21 | netflu      

#6楼 [楼主]   回复  引用  查看    

@书生
@netflu
Eilon(microsoft asp.net team)在他的blog上说要写一个关于测试asp.net控件的系列,不知道他会不会写下去。
2007-06-06 12:19 | Osamede      

#7楼 [楼主]   回复  引用  查看    

@明明MM
谢谢,呵呵。
2007-06-06 12:19 | Osamede      

#8楼    回复  引用  查看    

有时候写个单元测试,也是挺长代码的。运行起来速度也不快。
2007-07-20 13:41 | 风焰庄主      

#9楼    回复  引用  查看    

但谢谢LZ分享。
2007-07-20 13:42 | 风焰庄主      

#10楼    回复  引用    

@风焰庄主
恩,确实如此,到底如何更有效率,真的很难把握.
2007-07-28 19:26 | osamede [未注册用户]

#11楼 [楼主]   回复  引用  查看    

-------------------------
汉广同学正在找工作,你可以点击这里 ,浏览他的简历:-)
2008-02-26 15:53 | 汉广      

#12楼    回复  引用    

大哥,你发表的一篇往
XlsDocument xls = new XlsDocument(); //创建一个空的Excel文档
xls.Send(); //将文档发送到浏览器。
它的命名空间是什么啊,我一直都没有查到过,我应 using System.xml;但是不管事啊
期待您的回复,希望将答案发送到我的邮箱或QQ中
Email:luoquan99@gmail.com
QQ:446414937
2008-06-06 17:03 | 罗权 [未注册用户]