Even if available, I wouldn't recommend testing against the results of .toHtml()
- if you've ever looked at the html output of a VF page, you know that there is lots of extra bits added by the system - ids, classes, event handlers - that aren't guaranteed to not change. You are much better off inspecting and asserting against the object returned.
nowhere can I find a list of methods for what I can do with an ApexPages.Component object
The list is available, but it isn't very helpful. In particular, .expressions
(and .facets
, I would guess, although I did not test it) appears to be write-only. This leaves us with .childComponents
, but that's enough to traverse the tree of VF objects returned. So how to ensure that the results are correct?
I'd point out as a side note here that the degree to which you need to test depends on the amount of logic in your dynamic code. For example, in the sample code in @[Mohith Kumar]'s answer (and which my sample code, below, is based on) really only has one thing that needs to be tested - the conditional. Confirming that the method does or doesn't return a component is enough - the rest of the code that builds the pageBlock is basic VF; you should be testing your application logic, not the services provided by the platform.
That said, there will of course be more complex code where many parts of the dynamic response may depend on the inputs, and so it may be necessary to assert much of the response. There are three tools we can use to do so:
- We can use
.childComponents()
to traverse the tree of VF components returned.
- We can use the instanceOf operator to confirm that the VF components in the tree are of the expected type, allowing us to confirm (for example) that we got a grid instead of a table.
- We can cast any
ApexPages.Component
to it's actual type, allowing us to access all of the properties of the object.
Here's a simple demo controller, based on the sample code in Mohith's answer:
public class DynTestPageController{
public Component.Apex.pageBlock getStartpage(){
if(true){ //this would be a real conditional in real code.
Component.Apex.pageBlock pg=new Component.Apex.pageBlock(id='PanelId', title='Main Block');//formation of pageblock
Component.Apex.panelGrid pgrid=new Component.Apex.panelGrid(id='GridId');//formation of panelGrid
pgrid.columns=3;
Component.Apex.outputText outtx1=new Component.Apex.outputText();
outtxt1.value='Welcome to the start page';
Component.Apex.outputText outtxt2=new Component.Apex.outputText();
outtxt2.value='';
Component.Apex.CommandButton startbutton=new Component.Apex.CommandButton();
startbutton.Value='Begin';
startbutton.expressions.action='{!save}';
pg.childComponents.add(pgrid);
pgrid.childComponents.add(outtxt1);
pgrid.childComponents.add(outtxt2);
pgrid.childComponents.add(startbutton);
return pg;
}else {
return null;
}
}
}
And here's a test class to validate the dynamic VF generated:
@isTest
public class DynTestPageControllerTest{
@isTest
public static void testStartpage() {
DynTestPageController controller = new DynTestPageController();
Component.Apex.pageBlock pblk=controller.getstartpage();
system.assertNotEquals(null, pblk); //did we get a component?
system.assertEquals(pblk.title, 'Main Block'); //assert component property
system.assertEquals(1, pblk.childComponents.size()); //do we have correct # of children
//first (and only) child
system.assert(pblk.childComponents[0] instanceOf Component.apex.panelgrid); // correct type?
Component.apex.panelgrid pgrid = (Component.apex.panelgrid)pblk.childComponents[0]; // cast it to access props
system.assertEquals(3, pgrid.columns); //assert child component property
system.assertEquals(3, pgrid.childComponents.size()); // continuing down the tree...
//first child of panelgrid
system.assert(pgrid.childComponents[0] instanceOf Component.apex.outputtext);
Component.apex.outputText ot = (Component.apex.outputText)pgrid.childComponents[0];
system.assertEquals('Welcome to the start page', ot.value);
//second child of panelgrid
system.assert(pgrid.childComponents[1] instanceOf Component.apex.outputtext)
ot = (Component.apex.outputText)pgrid.childComponents[1];
system.assertEquals('', ot.value);
//third child of panelgrid
system.assert(pgrid.childComponents[2] instanceOf Component.apex.commandbutton);
Component.apex.commandButton btn = (Component.apex.commandButton)pgrid.childComponents[2];
system.assertEquals('Begin', btn.value);
system.assertEquals('#{save}', btn.action.getExpression());
}
}
Of course, you may need a little experimentation and cave-man debugging (a.k.a., System.Debug() calls) to determine the correct way to test some things. For example, see the last assert above - Originally, I was asserting for '{!save}'
, but apparently it is internally stored as '#{save}'
.
Updated 8 Sep 2013 to use instanceOf for type checking instead of toString. Thanks to @[Andrew Fawcett] for the suggestion.