好的。
所以我认为是时候进行单元测试了,因为每个人都在讨论它已经足够长的时间了。我已经安装了 NUnit 并阅读了一些“单元测试介绍”类型的教程。
我目前正在组合一个小框架来帮助重建我们的一个 Web 应用程序,因此我为我的框架创建了一个 VS2008 项目,并且我想随时对其进行单元测试。
我到底该如何对 WebControls 进行单元测试?这些方法都是受保护的或私有的,因为它是一个框架,所以除了 WebControls 之外没有别的东西。
任何指针?
伯恩斯
好的。
所以我认为是时候进行单元测试了,因为每个人都在讨论它已经足够长的时间了。我已经安装了 NUnit 并阅读了一些“单元测试介绍”类型的教程。
我目前正在组合一个小框架来帮助重建我们的一个 Web 应用程序,因此我为我的框架创建了一个 VS2008 项目,并且我想随时对其进行单元测试。
我到底该如何对 WebControls 进行单元测试?这些方法都是受保护的或私有的,因为它是一个框架,所以除了 WebControls 之外没有别的东西。
任何指针?
伯恩斯
您可以在不使用完整框架的情况下构建模型-视图-控制器或模型-视图-演示器类型的架构。您已经发现对 ui-components 进行单元测试很困难。有办法解决这个问题,但你可能不想走那条路。通常这会使你的测试很难维护,更多的维护噩梦是程序员可以做到的:-)
尝试在“控制器”或“演示者”类中分离出要测试的功能。然后测试那个类。为了使其更具可测试性,您可以将用户控件类(视图)隐藏在接口后面,并使控制器或演示者通过接口与视图对话。这样您就可以在测试中模拟视图。
我知道这听起来需要做很多工作,而且它似乎是一种解决方法,但如果你习惯了它,这是一个非常好的架构,它可以更容易地改变 ui 行为。当你真正需要它时,你总是可以开始使用“真正的”mvc 框架:-)
使用该assembly:InternalsVisibleTo
属性,您将能够访问这些私有成员。
把它放在你的 webcontrol 项目的AssemblyInfo.cs中(在Properties节点下)
[assembly:InternalsVisibleTo("YourTestProjectName")]
您已经找到了 ASP.NET 的最大痛点。至于阻碍单元测试的密封私有类。
这是 TDD 人员将使用 MVC 框架(ASP.NET MVC、Castle MonoRail)的主要原因,因为它提供了与视图模板和控制器逻辑的清晰分离。控制器是完全可测试的。
这是一篇旧文章,但我在 2004 年使用 NUnitASP 为 asp.net WebControls 编写 nunit 测试。那篇文章给出了一个详细的示例,使用他们创建相应的“Tester”类的概念来测试一个简单的控件,该类封装了你的控制细节来自你的测试。测试器也可以(应该)与您的控件在同一个程序集中,因此可以在它们之间共享一些东西(例如实用程序函数、常量等)。
我今天仍然使用该技术(以及其他人使用该技术的变体)来测试非常复杂的控件。
我希望这会有所帮助。
您还可以通过浏览器查看测试组件,就像用户使用WebAii等测试框架看到它们一样。我已经看到它有效并且非常酷。我还被告知您可以将其插入自动构建中,但我还没有看到。
希望能帮助到你 ...
上面提到的 MVC 框架是测试控件做什么的最好方法。然而,测试它是如何工作的有点不同。
这完全是袖手旁观,但您可以让用户控件公开一些受保护的方法和属性以返回验证信息,然后让测试用户控件继承它。该控件可以填充字段,按下按钮等等。有点乱,但它可以工作。
你也可以看看这个Rhino Igloo框架。它是用于 WebForms 的受损 MVC 框架。
Ivonna 可以在 Asp.Net 上下文中单独测试 WebControls 只需调用 session.GetControl("Path.ascx") 并验证它是否具有所有必要的属性。
你像这样测试它们:
[Test]
public void ConditionQueryBuilderTest_RendersProperHtml()
{
var sw = new StringWriter();
var queryBuilder = new ConditionQueryBuilderStub
{
ID = "UnitTestbuilder",
QueryBuilderURL = @"\SomeAspxPage\SomeWebMethod",
ResetQueryBuilderURL = @"\SomeAspxPage\OnQueryBuilderReset",
FilterValuesCollection = new Dictionary<int, string> { {15, "Some Condition"}}
};
queryBuilder.RenderAllContents(new HtmlTextWriter(sw));
AppendLog(sw.ToString());
Assert.AreEqual(ExpectedHtml, sw.ToString()); // ExpectedHTML is the raw expected HTML
}
这是我的存根:
internal class ConditionQueryBuilderStub : ConditionQueryBuilder // ConditionQueryBuilder is a WebControl
{
internal void RenderAllContents(HtmlTextWriter writer)
{
RenderContents(writer);
}
}