[Summer 16 introduces two new methods][1] 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[] bodies= [select body from EmailTemplate where developerName IN ('foo','bar')]; 


  [1]: https://developer.salesforce.com/docs/atlas.en-us.202.0.apexcode.meta/apexcode/apex_classes_email_outbound_messaging.htm?search_text=RenderEmailTemplateBodyResult