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:
我遇到了很多问题:
- The controls rely on HttpContext
- CreateChildControls is private
控件依赖于HttpContext
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导致。