MSTest测试ASP.NET含Web控件操作的后台Reset方法可行性及方案咨询
问题结论
直接对包含Web控件赋值操作的Reset()方法执行单元测试不支持。原因是MSTest单元测试运行时不会触发ASP.NET Web Form的页面生命周期,txtName服务器控件没有被实例化,直接调用Reset()会抛出NullReferenceException空引用异常。
可行解决思路
下面提供两种适配方案,可根据项目改造要求选择:
最小侵入改造方案(无需调整现有代码结构)
首先将页面后台中txtName控件的访问修饰符从默认的protected改为public或internal(如果用internal需要给测试项目添加[InternalsVisibleTo("你的测试项目名称")]程序集特性),之后在单元测试中手动初始化控件实例即可测试,示例MSTest代码如下:[TestClass] public class SamplePageTests { [TestMethod] public void Reset_WhenCalled_ClearsTxtNameValue() { // 实例化页面对象 var testPage = new samplepage(); // 手动初始化txtName控件并赋予初始值 testPage.txtName = new System.Web.UI.WebControls.TextBox { Text = "测试初始值" }; // 执行被测方法 testPage.Reset(); // 断言结果符合预期 Assert.AreEqual(string.Empty, testPage.txtName.Text); } }如果需要覆盖
Reset_Click事件方法,直接传入null作为sender、EventArgs.Empty作为参数调用该方法即可,测试逻辑和上述一致。分层解耦方案(推荐,符合可测试性设计规范)
将业务逻辑和Web控件操作分离,抽离独立的业务服务层,完全脱离Web上下文依赖,后续业务逻辑迭代也不需要修改页面代码,测试成本更低。
改造后代码示例:- 抽离业务逻辑层
// 业务服务类,无任何Web框架依赖 public class UserFormBusinessService { public string GetResetUserNameValue() { // 后续如果重置规则调整,比如改为默认值"请输入姓名",只需修改此处 return string.Empty; } }- 调整页面后台代码
public partial class samplepage : System.Web.UI.Page { private readonly UserFormBusinessService _formService = new UserFormBusinessService(); protected override void Reset_Click(object sender, EventArgs e) { Reset(); } public void Reset() { txtName.Text = _formService.GetResetUserNameValue(); } }- 单元测试代码(仅需测试业务逻辑层,无Web依赖)
[TestClass] public class UserFormBusinessServiceTests { [TestMethod] public void GetResetUserNameValue_ReturnsEmptyString() { var service = new UserFormBusinessService(); var result = service.GetResetUserNameValue(); Assert.AreEqual(string.Empty, result); } }如需覆盖页面的
Reset和Reset_Click方法,结合第一种方案的手动初始化控件方式补充测试即可。
两种方案都可以达到100%代码覆盖率的要求,第二种方案更适合长期维护的项目,可测试性和扩展性更好。
内容的提问来源于stack exchange,提问作者Vijay
相关产品推荐
相关产品推荐

