Summer 16 introduces two new methods that (finally) eliminate the clever hack by @pjcarly:
For VF, HTML, and Plain Text templates:
Messaging.SingleEmailMessage email =
Messaging.renderStoredEmailTemplate(templateId, whoId, whatId);
To get just the merged results from the templateBody (and any errors)
List<Messaging.RenderEmailTemplateBodyResult> resList =
Messaging.renderEmailTemplate(String whoId, String whatId, List<String> bodies)
where bodies
is a list of strings corresponding to the value of EmailTemplate.body
as queried from the database
String[]for bodies=(EmailTemplate et: [select bodyBody from EmailTemplate where developerNameDeveloperName IN ('foo','bar')];])
bodies.add(et.Body);