C#单元测试中System.Web.UI.WebControls.Panel返回null的问题如何解决
问题根因
ASP.NET 服务端控件在生产环境会由页面生命周期自动完成初始化,你在单元测试中直接new ExpenseReceipts()没有触发页面初始化流程,因此设计器类中声明的ResultPanel、NoItemsMessage、NoItemsPanel所有控件都是null,访问属性时直接抛出空指针异常,还没到你写的Shim拦截逻辑执行的环节。
你现有测试代码还有一个逻辑问题:重复给ShimControl.AllInstances.VisibleSetBoolean赋值,后写的委托会直接覆盖前者,所有控件调用Visible属性赋值都会触发flag置为true,无法准确验证是NoItemsPanel被设置为可见。
修复方案
用Shim直接为ExpenseReceipts类的控件属性返回模拟实例,再优化Visible赋值的判断逻辑即可,修复后的测试代码如下:
[TestMethod] public void HandleRecordsNotFound_ShouldMakeNoResultPanelVisible() { using (ShimsContext.Create()) { // 提前声明模拟控件实例,方便后续判断 var mockResultPanel = new Panel(); var mockNoItemsPanel = new Panel(); var mockNoItemsLabel = new Label(); bool noItemsPanelSetVisible = false; // Shim页面类的控件获取逻辑,返回我们提前创建的模拟实例 ShimExpenseReceipts.AllInstances.ResultPanelGet = instance => mockResultPanel; ShimExpenseReceipts.AllInstances.NoItemsPanelGet = instance => mockNoItemsPanel; ShimExpenseReceipts.AllInstances.NoItemsMessageGet = instance => mockNoItemsLabel; // 拦截Visible赋值,仅当操作的是NoItemsPanel且赋值为true时标记flag ShimControl.AllInstances.VisibleSetBoolean = (control, value) => { if (control == mockNoItemsPanel && value == true) { noItemsPanelSetVisible = true; } }; // 拦截Label的Text赋值、WebControl的ForeColor赋值,无额外逻辑 ShimLabel.AllInstances.TextSetString = (label, text) => { }; ShimWebControl.AllInstances.ForeColorSetColor = (webControl, color) => { }; ExpenseReceipts expenseReceipts = new ShimExpenseReceipts(); expenseReceipts.HandleRecordsNotFound(); Assert.IsTrue(noItemsPanelSetVisible); } }
如果遇到LayoutsPageBase初始化报错,可以额外加一行Shim基类的构造逻辑:
ShimLayoutsPageBase.AllInstances.Constructor = instance => { };
注意:如果代码中找不到
ShimExpenseReceipts类,需要在测试项目中为你的Web项目程序集添加Fakes引用,生成对应页面类的Shim代理。
内容的提问来源于stack exchange,提问作者C Puneeth
相关产品推荐
相关产品推荐

