0

I'm attempting to build my first test, which is for a trigger I am trying to push to production and running into a large number of issues. The first an foremost being that the trigger at the beginning was getting a <1% code coverage error. I'm still not entirely sure this is how to resolve that but I digress.

I've condensed everything down into the Trigger, a Class, and a test class.

When attempting to save the trigger with any reference to the class's or test class's methods I get the error:

Error: Compile Error: Method does not exist or incorrect signature: SendSpecificEmail(Id, EmailTemplate) at line 19 column 5

Trigger as I am trying to save it:

trigger EmailAssignedAM on Opportunity (after update) {

    Boolean email = false;

    Opportunity opp = new Opportunity();

    for(Opportunity op : Trigger.new){
        opp = [SELECT Id, Assigned_AM__c, StageName, Type FROM Opportunity WHERE Id = :op.Id];
    }

    if( opp.Type == 'LMS' || opp.Type == 'LEARN - PM'){
        email = true;
    }

    if( opp.StageName == 'Closed Won' && email == true){

    EmailTemplate et=[Select id from EmailTemplate where name=:'New Account Added'];

    SendSpecificEmail(opp.Assigned_AM__c, et);

    } 
}

Class:

public class SendSpecificEmail{

    public Id testObjectId {get;set;}

    public EmailTemplate testTemplate = new EmailTemplate();

    public void SendSpecificEmail( Id objectId, EmailTemplate template){

        //set test vars for the test method
        testObjectId = objectId;

        testTemplate = template;

        //run test to check if the information provided is valid
        //CheckInformation();

        List<Messaging.SingleEmailMessage> emails = new List<Messaging.SingleEmailMessage>();

         //initiallize messaging method
         Messaging.SingleEmailMessage singleMail = new Messaging.SingleEmailMessage();

         //set object Id
         singleMail.setTargetObjectId(objectId);

         //set template Id
         singleMail.setTemplateId(template.Id);

         //flag to false to stop inserting activity history
         singleMail.setSaveAsActivity(false);

         //add mail
         emails.add(singleMail);

         //send mail
         Messaging.sendEmail(emails); 

         //Send a debug log message to confirm the sent email
         System.debug('The message was sent to ' + objectId);  
    }
}

Test Class:

@isTest
public class TestSendSpecificEmail{

    public Id testObjectId {get;set;}

    public EmailTemplate testTemplate = new EmailTemplate();

    public void SendSpecificEmail( Id objectId, EmailTemplate template){

        //set test vars for the test method
        testObjectId = objectId;

        testTemplate = template;

        //run test to check if the information provided is valid
        CheckInformation();

        List<Messaging.SingleEmailMessage> emails = new List<Messaging.SingleEmailMessage>();

         //initiallize messaging method
         Messaging.SingleEmailMessage singleMail = new Messaging.SingleEmailMessage();

         //set object Id
         singleMail.setTargetObjectId(objectId);

         //set template Id
         singleMail.setTemplateId(template.Id);

         //flag to false to stop inserting activity history
         singleMail.setSaveAsActivity(false);

         //add mail
         emails.add(singleMail);

         //send mail
         Messaging.sendEmail(emails); 

         //Send a debug log message to confirm the sent email
         System.debug('The message was sent to ' + objectId);  
    }

    public void CheckInformation(){
        System.assert( testObjectId == null, 'The Object provided is Null');
        System.assert( testTemplate == null, 'The Template provided is Null');
        System.debug('EmailAssignedAM Values are valid.');
    }
}
1

You have some conceptual issues here

  1. Class SendSpecificEmail is doing its work through a constructor. Instead, you should have a class called something like UtilEmailServices which contains methods, most likely declared as static that do various useful things. One method would be sendSpecificTemplatedEmail(ID tgtObjId, ID templateId)
  2. Your testmethod merely needs to set up the testdata and then call UtilEmailServices.sendSpecificTemplatedEmail(..) to get code coverage. You don't replicate the code again in the testmethod as you have done. Note that testmethods won't actually send email
  3. Your trigger invokes UtilEmailServices.sendSpecificTemplatedEmail(..) in exactly the same way. However, since triggers can execute in bulk, you have to think through what you are going to do if 200 updates to the Opportunity occur in one transaction - you won't be able to send apex outbound emails for this kind of volume over the course of a day. Much, much better is to update the Opportunity in some way that causes a workflow to fire with an email alert (or Process Builder equivalent). This way you have much larger governor headroom
3
  • Thank you so much! That's what I didn't understand about tests. So with that, would I then just need to use tested classes in the trigger to get approved code coverage? – Cody Beaner Mar 31 '15 at 14:11
  • And to go off your note of sending it via workflow; How would I pass the email variable of the person defined in the Assigned_AM__c lookup field? – Cody Beaner Mar 31 '15 at 14:15
  • To answer your first question -- if you have a testmethod that updates an Opportunity such that the triggering condition to send an email occurs - then YES - that would provide code coverage. To answer your second question, you would need to copy the assigned_am__c.someemailField to somewhere in the Opportunity in a field of type Email for it to be available in the Email Alert. – cropredy Mar 31 '15 at 20:48
0

For the error you listed, you need to change SendSpecificEmail(opp.Assigned_AM__c, et) to

SendSpecificEmail s = new SendSpecificEmail(opp.Assigned_AM__c.id, et);

Regarding your digression on coverage, are you familiar with the Developer Console? It is extremely helpful and will highlight any lines that your test class is covering or failing to cover.

5
  • Assigned_AM__c is a lookup field, and doing the .id would just cause another error. And I am not familiar with it at all, any guides you can recommend on it's usage? – Cody Beaner Mar 30 '15 at 21:03
  • Sorry, just noticed this was in your constructor for SendSpecificEmail - you just need to instantiate an instance of your class. I updated the post accordingly. – Brian Mansfield Mar 30 '15 at 21:13
  • I've tried that and still get the same error – Cody Beaner Mar 30 '15 at 21:14
  • And if you go to Develop -> Apex Classes and click Develop Console, there's a panel on the bottom right that summarizes your org's code coverage. Double clicking on one of the classes will bring up the content of that class, with uncovered code highlighted in red and covered code highlighted in blue. – Brian Mansfield Mar 30 '15 at 21:15
  • that's just the thing though, I've been in there and it just says there is no code coverage, and I have no clue as how to give it coverage. – Cody Beaner Mar 30 '15 at 21:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.