Spiga

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

2007-06-05 11:51 by 汉广, 2497 visits, 网摘, 编辑
 

通常一个典型的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")]

 

 

 

 

 

 

 

Add your comment

12 条回复

  1. #1楼 沧海依粟      2007-06-05 20:28
    呵呵,代码工整,历害...
      回复  引用  查看    
  2. #2楼[楼主] Osamede      2007-06-05 21:12
    Eilon写的,Eilon是牛人啊,
    你要是说那俩行文字工整就好了,:-)。
      回复  引用  查看    
  3. #3楼 明明MM      2007-06-05 23:28
    思路严谨..表达清析..很有价值哦! 好好学习啰!呵呵~~
      回复  引用  查看    
  4. #4楼 书生[未注册用户]2007-06-06 09:23
    呵呵,谢谢博主的好文章

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

    只是建议而已,呵呵,还是谢谢您的文章
      回复  引用    
  5. #5楼 netflu2007-06-06 10:21
    今天才知道还可以这样对WEB控件进行单元测试
      回复  引用    
  6. #6楼[楼主] Osamede      2007-06-06 12:19
    @书生
    @netflu
    Eilon(microsoft asp.net team)在他的blog上说要写一个关于测试asp.net控件的系列,不知道他会不会写下去。
      回复  引用  查看    
  7. #7楼[楼主] Osamede      2007-06-06 12:19
    @明明MM
    谢谢,呵呵。
      回复  引用  查看    
  8. #8楼 风焰庄主      2007-07-20 13:41
    有时候写个单元测试,也是挺长代码的。运行起来速度也不快。
      回复  引用  查看    
  9. #9楼 风焰庄主      2007-07-20 13:42
    但谢谢LZ分享。
      回复  引用  查看    
  10. #10楼 osamede[未注册用户]2007-07-28 19:26
    @风焰庄主
    恩,确实如此,到底如何更有效率,真的很难把握.
      回复  引用    
  11. #11楼[楼主] 汉广      2008-02-26 15:53
    -------------------------
    汉广同学正在找工作,你可以点击http://www.cnblogs.com/osamede/archive/2008/02/26/1082044.html">这里 ,浏览他的简历:-)
      回复  引用  查看    
  12. #12楼 罗权[未注册用户]2008-06-06 17:03
    大哥,你发表的一篇往
    XlsDocument xls = new XlsDocument(); //创建一个空的Excel文档
    xls.Send(); //将文档发送到浏览器。
    它的命名空间是什么啊,我一直都没有查到过,我应 using System.xml;但是不管事啊
    期待您的回复,希望将答案发送到我的邮箱或QQ中
    Email:luoquan99@gmail.com
    QQ:446414937
      回复  引用    



发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 771944




相关文章:

相关链接: