Fo单元测试ASP.NET控件我需要一个存根页面。
我可以通过继承System.Web.UI.Page在单元测试中创建一个ASP.NET页面对象。 但是,我找不到设置Page.Form的方法。添加带有属性的表单(runat,server) 不起作用。在我的子类中重载表单不会提供所需的功能。
上下文: 我尝试对一些自制的ASP.NET控件进行单元测试。这些控件需要Page和Page.Form不能为空。
有什么建议吗?
答案 0 :(得分:3)
尝试定义实现所需方法和属性的IPage
和IForm
接口,并创建实现这些接口的类并包装Page
或Form
类。这样,您可以测试这些控件中的逻辑,而无需在单元测试期间调用ASP.NET框架。
<强>更新强>
覆盖页面属性会很脆弱,不建议这样做。相反,您应该尝试通过在不依赖于任何ASP.NET特定(难以测试)的部分的方法中提取逻辑来最小化不可测试代码的数量。看一下下面的例子:
public class MyLabel : Label
{
protected override override void RenderContents(HtmlTextWriter writer)
{
IPage page = new PageWrapper(this.Page);
this.MethodToTest(page);
base.RenderContents(writer);
}
internal void MethodToTest(IPage page)
{
// Work with IPage interface.
if (page.IsPostBack)
{
this.Text = string.Empty;
}
}
}
通过从难以测试的方法中提取逻辑,您可以直接在测试中调用这些提取的方法。例如:
[TestMethod]
public void MethodToTest_ScenarioToTest_ExpectedBehavior()
{
// Arrange
var label = new MyLabel();
var page = new TestPage()
{
IsPostBack = true
};
// Act
label.MethodToTest(page);
// Assert
Assert.IsTrue(string.Empty, label.Text);
}
如果你能够将测试中的代码提取到它自己的类并从WebControl中调用它,那就更好了。然而,这并非总是可行。
我希望这是有道理的。
答案 1 :(得分:1)
你到底想要测试什么?如果您正在测试的内容并不完全依赖于页面本身,那么您可以避免需要一个页面实例来完全为自己节省很多心痛。请看以下链接:
http://xunitpatterns.com/Humble%20Object.html
但是,如果您要测试的内容确实取决于页面类,请使用您自己的类来包装它,该类提供对数据的访问方法。然后将该类转换为接口,以用作方法或构造函数的参数。
示例:
public testPageNull_shouldThrowArgumentNullException()
{
PageWrappable nullPage = new MockPageWrappable();
nullPage.GetPage().Return(null);
CustomControl sut = new CustomControl(nullPage);
Assert.Fail("Exception not thrown");
}
public interface PageWrappable
{
//Gets Wrapped Page Instance
WrappedPage GetPage();
//GetSomethingFromTheForm
String GetFormValue(String Key);
}
答案 2 :(得分:0)
几年前,我遇到了与ASP.NET相同的问题,我们实现了Fowler's «Passive View» pattern,并设法对所有逻辑进行单元测试(并将相当愚蠢的视图的测试留给了手动测试)。