13

好的。

所以我认为是时候进行单元测试了,因为每个人都在讨论它已经足够长的时间了。我已经安装了 NUnit 并阅读了一些“单元测试介绍”类型的教程。

我目前正在组合一个小框架来帮助重建我们的一个 Web 应用程序,因此我为我的框架创建了一个 VS2008 项目,并且我想随时对其进行单元测试。

我到底该如何对 WebControls 进行单元测试?这些方法都是受保护的或私有的,因为它是一个框架,所以除了 WebControls 之外没有别的东西。

任何指针?

伯恩斯

4

9 回答 9

8

您可以在不使用完整框架的情况下构建模型-视图-控制器或模型-视图-演示器类型的架构。您已经发现对 ui-components 进行单元测试很困难。有办法解决这个问题,但你可能不想走那条路。通常这会使你的测试很难维护,更多的维护噩梦是程序员可以做到的:-)

尝试在“控制器”或“演示者”类中分离出要测试的功能。然后测试那个类。为了使其更具可测试性,您可以将用户控件类(视图)隐藏在接口后面,并使控制器或演示者通过接口与视图对话。这样您就可以在测试中模拟视图。

我知道这听起来需要做很多工作,而且它似乎是一种解决方法,但如果你习惯了它,这是一个非常好的架构,它可以更容易地改变 ui 行为。当你真正需要它时,你总是可以开始使用“真正的”mvc 框架:-)

于 2008-08-27T20:37:06.767 回答
5

使用该assembly:InternalsVisibleTo属性,您将能够访问这些私有成员。

把它放在你的 webcontrol 项目的AssemblyInfo.cs中(在Properties节点下)

[assembly:InternalsVisibleTo("YourTestProjectName")]
于 2008-08-27T20:22:11.530 回答
3

您已经找到了 ASP.NET 的最大痛点。至于阻碍单元测试的密封私有类。

这是 TDD 人员将使用 MVC 框架(ASP.NET MVC、Castle MonoRail)的主要原因,因为它提供了与视图模板和控制器逻辑的清晰分离。控制器是完全可测试的。

于 2008-08-27T20:23:20.777 回答
1

是一篇旧文章,但我在 2004 年使用 NUnitASP 为 asp.net WebControls 编写 nunit 测试。那篇文章给出了一个详细的示例,使用他们创建相应的“Tester”类的概念来测试一个简单的控件,该类封装了你的控制细节来自你的测试。测试器也可以(应该)与您的控件在同一个程序集中,因此可以在它们之间共享一些东西(例如实用程序函数、常量等)。

我今天仍然使用该技术(以及其他人使用该技术的变体)来测试非常复杂的控件。

我希望这会有所帮助。

于 2009-03-21T15:37:07.517 回答
1

您还可以通过浏览器查看测试组件,就像用户使用WebAii等测试框架看到它们一样。我已经看到它有效并且非常酷。我还被告知您可以将其插入自动构建中,但我还没有看到。

希望能帮助到你 ...

于 2009-09-23T18:46:19.250 回答
0

上面提到的 MVC 框架是测试控件做什么的最好方法。然而,测试它是如何工作的有点不同。

这完全是袖手旁观,但您可以让用户控件公开一些受保护的方法和属性以返回验证信息,然后让测试用户控件继承它。该控件可以填充字段,按下按钮等等。有点乱,但它可以工作。

于 2008-08-27T20:38:17.887 回答
0

你也可以看看这个Rhino Igloo框架。它是用于 WebForms 的受损 MVC 框架。

于 2008-09-03T16:25:29.640 回答
0

Ivonna 可以在 Asp.Net 上下文中单独测试 WebControls 只需调用 session.GetControl("Path.ascx") 并验证它是否具有所有必要的属性。

于 2009-09-23T18:41:54.907 回答
0

你像这样测试它们:

[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);
    }
}
于 2018-03-08T15:34:28.630 回答