You need to sign in to do that
Don't have an account?
Kev Brier
Test class Invocable Method calling @future class to send email with VF attachment
Hi,
Hoping someone can help to point us in the right direction, it seems that whatever we do, we are unable to get better than 26% code coverage with our Invocable Email Class calling an @future Method to send a single email with a visualforce attachement generated on the record. The Class works like a charm and does exactly what it is meant to do and we are even able to dummy an email being sent and assert the fact it was but it doesn't get close to covering the code.
Any guidance would be greatfully appreciate, as even though we run at 95% coverage, i'm not prepared to push a class with only 26% even though it works fully.
Please help save my sanity?
Hoping someone can help to point us in the right direction, it seems that whatever we do, we are unable to get better than 26% code coverage with our Invocable Email Class calling an @future Method to send a single email with a visualforce attachement generated on the record. The Class works like a charm and does exactly what it is meant to do and we are even able to dummy an email being sent and assert the fact it was but it doesn't get close to covering the code.
Any guidance would be greatfully appreciate, as even though we run at 95% coverage, i'm not prepared to push a class with only 26% even though it works fully.
Please help save my sanity?
Invoked from process builder with 100% coverage public class ProcessHandler { public class NPS{ @InvocableVariable(required=true) public Id npsid; @InvocableVariable(required=true) public String mname; @InvocableVariable(required=true) public String oname; @InvocableVariable(required=true) public String subject; @InvocableVariable(required=true) public String client; @InvocableVariable(required=true) public String md; @InvocableVariable(required=true) public String body; } @InvocableMethod public static void invokeapexcallout(NPS[] nps) { Futureapexcallout.apexcallout(nps[0].mname, nps[0].oname, nps[0].npsid, nps[0].subject, nps[0].client,nps[0].md,nps[0].body); } }
@Future Method with only 26% coverage public class Futureapexcallout{ @future(Callout=true) public static void apexcallout(string mname,string oname,Id NPSId, String subject, String client, string md, string body){ pageReference pdfPage = Page.NPS_Survey; pdfPage.getParameters().put('id',NPSID); if(Test.isRunningTest()){ blob b = blob.valueOf('Unit.Test'); }else{ blob b = pdfpage.getContentaspdf(); Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage(); Messaging.EmailFileAttachment efa1 = new Messaging.EmailFileAttachment(); efa1.setFileName('NPS.pdf'); efa1.setBody(b); String addresses; email.setSubject(subject); email.setToAddresses(new List<String> {mname}); email.setCCAddresses(new List<String> {oname}); email.setPlainTextBody(body); email.setFileAttachments(new Messaging.EmailFileAttachment[] {efa1}); Messaging.SendEmailResult [] r = Messaging.sendEmail(new Messaging.SingleEmailMessage[] {email}); } } }
Test Class, probably really badly written :) @isTest private class testProcessHandler { private static testMethod void testProcessHandler() { test.startTest(); User u2 = new User(Alias = 'nUr32', Email='newuser@testorg32.com', EmailEncodingKey='UTF-8', LastName='Testing12', LanguageLocaleKey='en_US', LocaleSidKey='en_US', ProfileId = '00e90000001yvFD' , TimeZoneSidKey='America/Los_Angeles', UserName='newuser32@testorg.com',External_Use__c='SRK1132AA',Operating_Country__c='Global',Region__c='Global' ,Team__c='Client Services - Global'); insert u2; Account a = new Account(Name = 'Test A', BillingCountry = 'UK', Ownership_Type__c = 'Private', Phone = '07826533392', Industry = 'Property development & management', Type = 'Customer Direct'); insert a; Contact c = new Contact (FirstName='Test', LastName='Test', AccountId = a.Id, Phone = '07826533392'); insert c; Net_Promoter__c n = new Net_Promoter__c (Account__c=a.Id, Assigned_To__c=u2.id, Client_Visiting__c=c.id, Activity_Date__c = datetime.newInstance(2017, 9, 15, 12, 30, 0), End_Time__c=datetime.newInstance(2017, 9, 15, 14, 30, 0), Site_Location__c='Test' ); insert n; n.Survey_Status__c='Complete'; n.Score_Updated__c=TRUE; update n; List<ProcessHandler.NPS> Params = new List<ProcessHandler.NPS>(); ProcessHandler.NPS p = new ProcessHandler.NPS(); p.npsid = n.id; p.mname = n.MD_Name__c; p.oname = n.Ops_Director__c; p.subject = n.subject__c; p.client = n.client_visiting__r.FirstName; p.md = n.MD_Email__c; p.body = n.Body__c; Params.add(p); ProcessHandler.Invokeapexcallout(params); Futureapexcallout.apexcallout(n.MD_Name__c, n.Ops_Director__c, n.id, n.subject__c,n.client_visiting__r.FirstName, n.MD_Name__c, N.Body__c ); Integer invocations = Limits.getEmailInvocations(); pageReference pdfPage = Page.NPS_Survey; pdfPage.getParameters().put('id',n.id); if(Test.isRunningTest()){ blob b = blob.valueOf('Unit.Test'); }else{ blob b = pdfpage.getContentaspdf(); Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage(); Messaging.EmailFileAttachment efa1 = new Messaging.EmailFileAttachment(); efa1.setFileName('NPS.pdf'); String addresses; email.setSubject(n.subject__c); email.setToAddresses(new List<String> {n.MD_Name__c}); email.setCCAddresses(new List<String> {n.Ops_Director__c}); email.setPlainTextBody(N.Body__c); email.setFileAttachments(new Messaging.EmailFileAttachment[] {efa1}); Messaging.SendEmailResult [] r = Messaging.sendEmail(new Messaging.SingleEmailMessage[] {email}); test.stopTest(); system.assertEquals(p.npsid, n.id); system.assertEquals(1, invocations, '1 email should be sent'); } } }
2) In testProcessHandler class, remove the following lines. ProcessHandler.Invokeapexcallout(params); should call your apexcallout method. This need not be called again.
All Answers
Move the email logic out of the else condition in 'Futureapexcallout'. See if this works.
Thanks,
Alex.
I've seen some stuff about not using getcontentaspdf in test classes since winter 16 but again we're struggling to get the test to pass without this.
Are you able to share how this should be annotated?
Looks like all the variables on the test class are all null, even though the parameters have been set above.
I can't see how the test should fail with this subtle change.
2) In testProcessHandler class, remove the following lines. ProcessHandler.Invokeapexcallout(params); should call your apexcallout method. This need not be called again.
Making the relevant changes doesn't enable the test class to pass, we still keep getting the same errors as we did before, email body missing etc.
However, the code coverage on the future callout now shows 94% but continues to fail. I don't think i've ever seen this before, how can it fail but show such high coverage. Its not like we lose the coverage on the process handler, this still continues to show 100%.
Clearly we're very close and something really minimal is wrong but it's not obvious to me.
I've seen lots of stuff about not using GetContentAsPDF in a test class and therefore I'm sure this is probably the issue. Whilst we still seem to run into the problem the variables are null whatever we do and I'm not getting the same errors as others do when using getcontent.
If you do have any other thoughts, please go ahead and share them. Hopefully helping me and others that land on this post.