I have an Apex controller method that returns a Component.Apex.OutputPanel
for use in a <apex:dynamicComponent />
tag. How do I do a unit test that asserts that the controller is outputting the correct HTML in the OutputPanel? That is, in my test I call the method and can make sure that the OutputPanel is non-null, but I can't find documentation on what properties the OutputPanel has other than the attributes one would use if creating one in code. I would have expected either some kind of .toHTML()
or a meaningful .toString()
or something, or ideally some way of accessing the object model that the OutputPanel represents, something like a DOM I guess. I feel like I must just be missing something obvious. What am I missing? What's the best way to unit test the code for an Apex Controller Dynamic Component?
Thank you.
Edit 9/3/13: I think the piece I'm missing is mainly the type library for the built-in force.com classes. That is, in my test I can take the output of my controller methods and call .childComponents
in order to get a List<ApexPages.Component>
, but nowhere can I find a list of methods for what I can do with an ApexPages.Component
object. Is there a page in the documentation that I just keep on missing? I feel like I have to be the only person trying to unit test dynamic components, which doesn't make any sense. Thanks again.
Best Answer
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.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:
.childComponents()
to traverse the tree of VF components returned.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:
And here's a test class to validate the dynamic VF generated:
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.