views:

43

answers:

1

Hi,

I want to unit test my rendering engine for an ASP.NET app. I have some custom controls created in that app. Most of those control rely on having CreateChildControls() method called by the ASP.Net engine wheather during initial call or a postback. When running a test CreateChildControls() does not get called and the control is in an "invalid" state.

As a workaround to get the tests going I explicitly call some other public method that calls EnsureChildControls() in it. This in effect causes CreateChildControls() to be executed and the control being initialized properly (just as it would normally when hosted on web server). I would like to get rid of that extra method call and the control to still be in a proper state for testing.

Are there any elegant solutions to this problem?

+1  A: 

Hey,

You could alternatively use reflection to call CreateChildControls directly, thereby escaping the need to use the public method to invoke it. That would be easy enough:

var methodInfo = control.GetType().GetMethod("CreateChildControls", BindingFlags.Instance | BindingFlags.NonPublic);
methodInfo.Invoke(control, new object[] { });

You could embed this code somewhere so that you only need to do this once and reuse it.

EDIT: You could have your test inherit from your control too, so you can invoke some of these methods directly. But you have to instantiate your control by instantiating the test and not the control, as in:

public class CtlTest : Ctl
{
  [Test]
  public void A()
  {
    var ctl = new CtlTest();
    ctl.RecreateChildControls(); //protected, but can be accessed because of inheritance

  }
}

HTH.

Brian
Thanks for the tip. I thought about using reflection but decided not to use it. I would like to have something to emulate normal flow of methods. I tried adding my controls on some containers but that didn't trigger method calls either.
Konrad
CompositeControl has a RecreateChildControls method you could take advantage of. You could also try having your test inherit from your control so you can execute methods directly. Things are different outside of the web environment, and that's the difficulty. I've also done testing by creating a test page class that has a public method called FireEvent and allows me to manually trigger lifecycle methods, which trickle down to its child controls. That was helpful, but it only helps so far because some things are embedded in the framework.
Brian
Test page seems like a good idea. A bit more work than I expected, but might be the easiest way after all. As for the testing classes inheriting from the ones being tested - it is interesting but I can't say I fully like the idea. Creating additional classes inheriting from the tested ones and 'using' them in the test sounds better, but it is more work at the same time. I will think and try to get my head around this concept. Thanks Brian.
Konrad