如何测试asp.net服务器控件

时间:2021-05-24 15:53:01

We have developed a number of ASP.Net server controls and we need to test them. I want to instantiate a control, set some properties, call CreateChildControls and test the control-hierarchy.

我们开发了许多ASP.Net服务器控件,我们需要对它们进行测试。我想实例化一个控件,设置一些属性,调用CreateChildControls并测试控件层次结构。

I run into a number of problems:

我遇到了很多问题:

  1. The controls rely on HttpContext
  2. 控件依赖于HttpContext

  3. CreateChildControls is private
  4. CreateChildControls是私有的

Even adding a single child control to the controls collection calls the ResolveAdapter() method which relies on HttpContext.

即使向控件集合添加单个子控件,也会调用ResolveAdapter()方法,该方法依赖于HttpContext。

How can I get around this?

我怎么能绕过这个?

p.s. I do not wish to test the controls on a page (!).

附:我不想测试页面上的控件(!)。

1 个解决方案

#1


It sounds a lot like you don't care about the actual rendering of the control at all, but rather the logic contained within the control. For that I would suggest that you have another problem besides the inability to test the control outside the HttpContext.

这听起来很像你根本不关心控件的实际渲染,而是控件中包含的逻辑。为此我建议除了无法在HttpContext之外测试控件之外还有另一个问题。

If the logic only pertains to the control, then you should trust the framework to do it's job, and drop the control on a page to see if it works properly. If the logic you are attempting to test is business logic, then you need to refactor.

如果逻辑仅适用于控件,那么您应该信任框架来完成它的工作,并将控件放在页面上以查看它是否正常工作。如果您尝试测试的逻辑是业务逻辑,那么您需要重构。

Pull out the business logic into a seperate Project/Dll somewhere, and think about implementing a MVP pattern with your server control. You don't have to go with a big heavy framework like WCSF either. Conceptually you can implement this with little effort.

将业务逻辑拉出到单独的Project / Dll中,并考虑使用服务器控件实现MVP模式。你也不必像WCSF这样的大型框架。从概念上讲,您可以轻松实现这一点。

Create an interface that represents the values on your view:

创建一个表示视图上的值的界面:

public interface IOrderView
{
    Int32 ID{get; set;}
    String Name{get; set;}
    List<Item> Items {set;}
}

Once this is defined, you need a presenter that exercises this view:

定义完成后,您需要一个演示此视图的演示者:

public class OrderPresenter
{
    public IOrderView View {get; set;}

    public void InitializeView()
    {
        //Stuff that only happens when the page loads the first time

        //This is only for an example:
        var order = Orders.GetOrder(custId);

        View.ID = order.ID;
        View.Name = order.Name;
        View.Items = order.Items;
    }

    public void LoadView()
    {
        //Stuff that happens every page load
    }
}

Now your server control can implement this interface, and initialize itself with the OrderPresenter

现在,您的服务器控件可以实现此接口,并使用OrderPresenter初始化自身

public class OrderControl: Panel, IOrderView
{
    private OrderPresenter Presenter{get; set;}

    public OrderControl()
    {
        //Create new presenter and initialize View with reference
        // to ourselves
        Presenter = new OrderPresenter{View = this;}
    }

    protected override void OnLoad(EventArgs e)
    {
        if(Page.IsPostback)
        {
            _presenter.InitializeView();
        }

        _presenter.LoadView();

        //Other normal onload stuff here...
    }

    //Now for the interface stuff
    public Int32 ID
    {
        get{ return Int32.Parse(lblOrderId.Text); } 
        set{ lblOrderId.Text = value.ToString(); }
    }

    public String Name
    {
        get{ return lblOrderName.Text; } 
        set{ lblOrderName.Text = value; }
    }

    public List<Item> Items 
    {
        set
        {
            gvItems.DataSource = value;
            gvItems.DataBind();
        }
    }
}

And there you have it! You should be able to write unit tests against the OrderPresenter now using a stubbed out View. No HttpContext required, and you have cleaner seperation of concerns.

你有它!您现在应该能够使用存根视图对OrderPresenter编写单元测试。不需要HttpContext,并且您可以更清楚地分离关注点。

If you already have all your business logic seperated out then I appologize, but I can't think of any other reason to test a server control outside the ASP.Net runtime besides needing to verify actual business logic. If this is the case, then I would highly encourage you to refactor now before you realize the maintenance nightmare this will eventually cause via Leaky Abstractions.

如果您已将所有业务逻辑分离出来,那么我会道歉,但除了需要验证实际业务逻辑之外,我想不出在ASP.Net运行时之外测试服务器控件的任何其他原因。如果是这种情况,那么我会强烈建议您在实现维护噩梦之前进行重构,这最终将通过Leaky Abstractions导致。

#1


It sounds a lot like you don't care about the actual rendering of the control at all, but rather the logic contained within the control. For that I would suggest that you have another problem besides the inability to test the control outside the HttpContext.

这听起来很像你根本不关心控件的实际渲染,而是控件中包含的逻辑。为此我建议除了无法在HttpContext之外测试控件之外还有另一个问题。

If the logic only pertains to the control, then you should trust the framework to do it's job, and drop the control on a page to see if it works properly. If the logic you are attempting to test is business logic, then you need to refactor.

如果逻辑仅适用于控件,那么您应该信任框架来完成它的工作,并将控件放在页面上以查看它是否正常工作。如果您尝试测试的逻辑是业务逻辑,那么您需要重构。

Pull out the business logic into a seperate Project/Dll somewhere, and think about implementing a MVP pattern with your server control. You don't have to go with a big heavy framework like WCSF either. Conceptually you can implement this with little effort.

将业务逻辑拉出到单独的Project / Dll中,并考虑使用服务器控件实现MVP模式。你也不必像WCSF这样的大型框架。从概念上讲,您可以轻松实现这一点。

Create an interface that represents the values on your view:

创建一个表示视图上的值的界面:

public interface IOrderView
{
    Int32 ID{get; set;}
    String Name{get; set;}
    List<Item> Items {set;}
}

Once this is defined, you need a presenter that exercises this view:

定义完成后,您需要一个演示此视图的演示者:

public class OrderPresenter
{
    public IOrderView View {get; set;}

    public void InitializeView()
    {
        //Stuff that only happens when the page loads the first time

        //This is only for an example:
        var order = Orders.GetOrder(custId);

        View.ID = order.ID;
        View.Name = order.Name;
        View.Items = order.Items;
    }

    public void LoadView()
    {
        //Stuff that happens every page load
    }
}

Now your server control can implement this interface, and initialize itself with the OrderPresenter

现在,您的服务器控件可以实现此接口,并使用OrderPresenter初始化自身

public class OrderControl: Panel, IOrderView
{
    private OrderPresenter Presenter{get; set;}

    public OrderControl()
    {
        //Create new presenter and initialize View with reference
        // to ourselves
        Presenter = new OrderPresenter{View = this;}
    }

    protected override void OnLoad(EventArgs e)
    {
        if(Page.IsPostback)
        {
            _presenter.InitializeView();
        }

        _presenter.LoadView();

        //Other normal onload stuff here...
    }

    //Now for the interface stuff
    public Int32 ID
    {
        get{ return Int32.Parse(lblOrderId.Text); } 
        set{ lblOrderId.Text = value.ToString(); }
    }

    public String Name
    {
        get{ return lblOrderName.Text; } 
        set{ lblOrderName.Text = value; }
    }

    public List<Item> Items 
    {
        set
        {
            gvItems.DataSource = value;
            gvItems.DataBind();
        }
    }
}

And there you have it! You should be able to write unit tests against the OrderPresenter now using a stubbed out View. No HttpContext required, and you have cleaner seperation of concerns.

你有它!您现在应该能够使用存根视图对OrderPresenter编写单元测试。不需要HttpContext,并且您可以更清楚地分离关注点。

If you already have all your business logic seperated out then I appologize, but I can't think of any other reason to test a server control outside the ASP.Net runtime besides needing to verify actual business logic. If this is the case, then I would highly encourage you to refactor now before you realize the maintenance nightmare this will eventually cause via Leaky Abstractions.

如果您已将所有业务逻辑分离出来,那么我会道歉,但除了需要验证实际业务逻辑之外,我想不出在ASP.Net运行时之外测试服务器控件的任何其他原因。如果是这种情况,那么我会强烈建议您在实现维护噩梦之前进行重构,这最终将通过Leaky Abstractions导致。