function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Angel Esau Vazquez lagos 5Angel Esau Vazquez lagos 5 

Help me with a test class, I need to cover the coverage percentage, I have 70%

I am a beginner in apex. I have written this kind of test, but it makes some mistakes, someone can tell me what is wrong or how to do it better.
I only have 60% coverage...

User-added image
The contacts to which a template with an attached file will be sent are selected.
The file is not mandatory.
In the custom button, only the subject and body are written and the template is not taken.

These are my codes.
****Visualforce*****
<apex:page controller="ControllerEnviaEmailInscripciones" doctype="html-5.0" language="es"> 
    <apex:form id="frm" acceptcharset="UTF-8">
      <apex:pageBlock >
          
          <apex:pageBlockSection columns="1">
              <apex:pageBlockTable value="{!models}" var="m">
                <apex:column headerValue="Acción" >
                    <apex:inputcheckbox value="{!m.flag}"/> 
                </apex:column>
                <apex:column headerValue="Nombre de la Inscripción">
                       <apex:outputField value="{!m.std.Name}"/>
                </apex:column>
                <apex:column headerValue="Contacto">
                         <apex:outputField value="{!m.std.Contacto__r.Name}"/>
                </apex:column>
                <apex:column headerValue="Cliente">
                        <apex:outputField value="{!m.std.Cliente__r.Name}"/> 
                </apex:column>
                <apex:column headerValue="Email">
                       <apex:outputField value="{!m.std.CorreoElectronico__c}"/>
                </apex:column>
                <apex:column headerValue="Número de Inscripción">
                        <apex:outputField value="{!m.std.NumeroInscripcion__c}"/>
                </apex:column>  
                <apex:column headerValue="Estado">
                        <apex:outputField value="{!m.std.Estado__c}"/>
                </apex:column>
              </apex:pageBlockTable>      
          </apex:pageBlockSection>
          
           <apex:pageBlock > 
        <!--  <apex:outputLabel value="Nombre del Archivo" for="fileName"/>
              <apex:inputText value="{!attachment.name}" id="fileName"/> -->
              <apex:outputLabel value="Archivo" for="file"/>
              <apex:inputFile value="{!attachment.body}" filename="{!attachment.name}" id="file" />
              <apex:messages style="font-size: 100%; color: blue;"/>
           </apex:pageBlock> 
       <!------------------------Sección de Email Personalizado--------------------------->  
           <apex:pageBlock > 
              <apex:commandButton value="{!Personalizaremail}" action="{!click}"/>     
                
               <apex:pageBlockSection id="thePanel" rendered="{!thePanel}">
                  <apex:pageBlockSectionItem >
                      <a style="font-family: Arial; font-size: 10pt;">Asunto:</a>
                      <apex:inputText value="{!asunto}" style="font-family: Arial; font-size: 10pt;" size="80" /> 
                  </apex:pageBlockSectionItem><br/> 
                  
                  <apex:pageBlockSectionItem >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
                  	  <apex:inputTextarea value="{!texto}" rows="15" cols="91" lang="es"/> <!-- lang="es" richText="true"-->
                  </apex:pageBlockSectionItem><br/>
               </apex:pageBlockSection> 
               
           </apex:pageBlock> 
          
          <apex:pageblockButtons >
               <apex:commandButton value="Enviar Email" action="{!send}" onclick="if(!confirm('Estás seguro de enviarlo?')) return false;"/>
          </apex:pageblockButtons>
     
      </apex:pageBlock> 
  </apex:form>
</apex:page>
***Controller***
public class ControllerEnviaEmailInscripciones{

     public String Personalizaremail {get; set;}
     public Boolean thePanel         {get; set;}
     public String asunto            {get; set;}
     public String texto             {get; set;}
    
     public Attachment attachment {
        get {
            if (attachment == null)
                attachment = new Attachment();
            return attachment;
        }
        set;
     }
        
    public class ModelClass {
        public Inscripcion__c std  {get; set;}
        public Boolean flag        {get; set;}
    
    ModelClass(Inscripcion__c std) {
            this.std = std;
         // this.flag = true;
         }
     } 

    public List<ModelClass> models {get; set;}

    public ControllerEnviaEmailInscripciones() {
       Personalizaremail ='Email personalizado';
       String IdCapacitacion = System.currentPageReference().getParameters().get('id');
       models = new List<ModelClass>();
       for (Inscripcion__c c : [SELECT Id, Capacitacion__c, Estado__c, Name, NumeroInscripcion__c, Contacto__r.Name, CorreoElectronico__c, Cliente__r.Name 
                                FROM Inscripcion__c WHERE Capacitacion__c =:IdCapacitacion AND Contacto__r.email != NULL order by name limit 100]) {
            models.add(new ModelClass(c));
        }
     }
  
   public void click(){
       if (Personalizaremail == 'Email personalizado'){
           Personalizaremail ='Ocultar sección';
           thePanel = true;
       } else if (Personalizaremail == 'Ocultar sección') {
           Personalizaremail ='Email personalizado';
           thePanel = false;
       }
    }
    
    public PageReference send() {
 if (Personalizaremail == 'Email personalizado')  {        
     try {  
          EmailTemplate template = [ Select Id from EmailTemplate where developername = 'Capacitacion'];
         
            List<Messaging.Emailfileattachment> fileAttachments = new List<Messaging.Emailfileattachment>();
            Messaging.Emailfileattachment attachmentForMail = new Messaging.Emailfileattachment();
            attachmentForMail.setFileName(attachment.name); 
            attachmentForMail.setBody(attachment.Body);
            fileAttachments.add(attachmentForMail);
    
              Messaging.SingleEmailMessage[] messages = new Messaging.SingleEmailMessage[] {};
                for (ModelClass m : models) {
                    if (m.flag) {
                        Messaging.SingleEmailMessage message = new Messaging.SingleEmailMessage();
                        message.setTargetObjectId(m.Std.Contacto__r.Id);
                        message.setTemplateId(template.Id);
                           if(attachment.name !=NULL && attachment.Body !=NULL) {//verificamos que hay un archivo adjunto
                              message.setFileAttachments(fileAttachments);
                          } 
                        messages.add(message);
                     }
                  }
             Messaging.sendEmail(messages, true );
            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.CONFIRM,'Email enviado correctamente.'));
        } Catch(Exception e){
                e.getMessage();
            } finally {
             attachment.Body = null;
            } 
   } else if (Personalizaremail == 'Ocultar sección'){   //termina if (Personalizaremail == 'Ocultar sección')
         try {  
         
            List<Messaging.Emailfileattachment> fileAttachments = new List<Messaging.Emailfileattachment>();
            Messaging.Emailfileattachment attachmentForMail = new Messaging.Emailfileattachment();
            attachmentForMail.setFileName(attachment.name); 
            attachmentForMail.setBody(attachment.Body);
            fileAttachments.add(attachmentForMail);
    
              Messaging.SingleEmailMessage[] messages = new Messaging.SingleEmailMessage[] {};
                for (ModelClass m : models) {
                    if (m.flag) {
                        Messaging.SingleEmailMessage message = new Messaging.SingleEmailMessage();
                        message.setTargetObjectId(m.Std.Contacto__r.Id);
                        message.setSubject(asunto);
                        message.setPlainTextBody(texto);
                          if(attachment.name !=NULL && attachment.Body !=NULL) {
                              message.setFileAttachments(fileAttachments);
                          } 
                        messages.add(message);
                     }
                  }
             Messaging.sendEmail(messages, true );
            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.CONFIRM,'Email enviado correctamente.'));
        } Catch(Exception e){
                e.getMessage();
            } finally {
             attachment.Body = null;
            } 
     }
    return null;  
   } 
   
}

***test class****
 
private class Test_ControllerEnviaEmailInscripciones {
  
    @isTest static void enviaEmail(){
        
     Account a = New Account();
        a.Name ='Alfredo';
        a.NombreComercial__c ='Alberto';
        a.GeneroCapital__c ='Hombre';
        insert (a);
        
     List<Contact> contactList = new List<Contact>();
        contactList.add(Util.createContact(a.Id, 'test contact2', 'email1@test.com', false));
        contactList.add(Util.createContact(a.Id, 'test contact2', 'email2@test.com', false));
        insert contactList;
     
  Test.startTest();
        
     Capacitacion__c cap = New Capacitacion__c();
        cap.Name ='Multple capacitacion';
        cap.TipoCapacitacion__c='Programa';
        cap.ClasificacionFormacion__c='Principiante';
        cap.AreaPromueveCurso__c='CACEX';
        cap.LugarImparte__c='Procomer';
        cap.FechaInicial__c= System.today() + 4;
        insert(cap);
       
      Inscripcion__c insc = New Inscripcion__c();
        insc.Capacitacion__c = cap.Id;
        insc.Cliente__c=a.Id;
        insc.Contacto__c=contactList[0].Id;
        insc.Name =contactList[0].Name;
        insc.CorreoElectronico__c=contactList[0].Email;
        insc.Estado__c='Asiste';
        insc.RegistroAsistencia__c= System.today()+ 1;
        insc.FechaConfirmacion__c=  System.today() + 2;
        insc.NumeroInscripcion__c= '1';
        insert(insc);
        
        Attachment attach=new Attachment();   	
    	attach.Name='Unit Test Attachment';
    	Blob bodyBlob=Blob.valueOf('Unit Test Attachment Body');
    	attach.body=bodyBlob;
        attach.parentId=cap.id;
        insert attach;
       
        PageReference pref = Page.EnviaEmailInscripciones;
        pref.getParameters().put('id', cap.id);
        Test.setCurrentPage(pref);
        
        ControllerEnviaEmailInscripciones envEmail = New ControllerEnviaEmailInscripciones();
        envEmail.texto ='test envía';
        envEmail.asunto='test asunto';
          pref = envEmail.send();
       
        envEmail.click();
 
        Test.stopTest();    
    }
   
    
    
    /***********************************test 2 - Parte seccion oculta *************************************************/

    
     @isTest static void enviaEmail2(){
        
     Account a = New Account();
        a.Name ='Alfredo';
        a.NombreComercial__c ='Alberto';
        a.GeneroCapital__c ='Hombre';
        insert (a);
        
     List<Contact> contactList = new List<Contact>();
        contactList.add(Util.createContact(a.Id, 'test contact1', 'email1@test.com', false));
        contactList.add(Util.createContact(a.Id, 'test contact2', 'email2@test.com', false));
        insert contactList;
     
  Test.startTest();
        
     Capacitacion__c cap = New Capacitacion__c();
        cap.Name ='Multple capacitacion';
        cap.TipoCapacitacion__c='Programa';
        cap.ClasificacionFormacion__c='Principiante';
        cap.AreaPromueveCurso__c='CACEX';
        cap.LugarImparte__c='Procomer';
        cap.FechaInicial__c= System.today() + 4;
        insert(cap);
       
        Inscripcion__c insc = New Inscripcion__c();
        insc.Capacitacion__c = cap.Id;
        insc.Cliente__c=a.Id;
        insc.Contacto__c=contactList[0].Id;
        insc.Name =contactList[0].Name;
        insc.CorreoElectronico__c=contactList[0].Email;
        insc.Estado__c='Asiste';
        insc.RegistroAsistencia__c= System.today()+ 1;
        insc.FechaConfirmacion__c=  System.today() + 2;
        insc.NumeroInscripcion__c= '1';
        insert (insc); 
       
       Inscripcion__c insc2 = New Inscripcion__c();
        insc2.Capacitacion__c = cap.Id;
        insc2.Cliente__c=a.Id;
        insc2.Contacto__c=contactList[1].Id;
        insc2.Name =contactList[1].Name;
        insc2.CorreoElectronico__c=contactList[1].Email;
        insc2.Estado__c='Asiste';
        insc2.RegistroAsistencia__c= System.today()+ 1;
        insc2.FechaConfirmacion__c=  System.today() + 2;
        insc2.NumeroInscripcion__c= '2';
        insert (insc2); 
         
        Attachment attach=new Attachment();   	
    	attach.Name='Prueba Adjunto';
    	Blob bodyBlob=Blob.valueOf('Cuerpo del Archivo');
    	attach.body=bodyBlob;
        attach.parentId=cap.id;
        insert attach;
        
       // System.currentPageReference().getParameters().put('id', cap.Id);
        PageReference pref = Page.EnviaEmailInscripciones;
        pref.getParameters().put('id', cap.id);
        Test.setCurrentPage(pref);
       
        ControllerEnviaEmailInscripciones envEmail = New ControllerEnviaEmailInscripciones();
         
        envEmail.texto ='test envía';
        envEmail.asunto='test asunto';
        envEmail.Personalizaremail = 'Ocultar sección';
       
       pref = envEmail.send();
        envEmail.click();

        Test.stopTest();    
    }
}

​​​​​​​
scox67scox67
Hi Angel,

Thanks for posting a great question. Unit testing is very important in software development. A certain amount of code coverage is required by Salesforce, but more importantly, unit tests verify the correctness of your code, make your code easier to maintain, and provide usage examples. When one of my methods is difficult to test, it's usually because I haven't designed the method well. You might consider some of these ideas from my book, Salesforce Defect Domination (http://force-code.com/salesforce-defect-domination-a-handbook-for-finding-fixing-and-preventing-defects-in-force-com-development/):
  • Design each method to accomplish a single task.
  • Reduce complexity.  Add assertions and contracts instead of conditionals and defensive code.
  • Isolate complexity.  Put extra effort into making sure complex logic is thoroughly testable.
  • Reuse code.
Let's look at a possible redesign of your "send" method, for example:
public void send() {
    try {
        String templateId = getEmailTemplateId(Personalizaremail);
        Messaging.SingleEmailMessage[] messages = generateEmails(templateId);
        Messaging.sendEmail(messages, true);
        ApexPages.addMessage(new ApexPages.message(ApexPages.severity.CONFIRM,'Email enviado correctamente.'));
    } Catch (Exception e) {
        ApexPages.addMessages(e);
    } finally {
        attachment.Body = null;
    } 
}

@TestVisible private static Messaging.SingleEmailMessage[] generateEmails(String emailTemplateId, ModelClass[] models) {
    List<Messaging.Emailfileattachment> fileAttachments = new List<Messaging.Emailfileattachment>();
    Messaging.Emailfileattachment attachmentForMail = new Messaging.Emailfileattachment();
    attachmentForMail.setFileName(attachment.name); 
    attachmentForMail.setBody(attachment.Body);
    fileAttachments.add(attachmentForMail);

    Messaging.SingleEmailMessage[] messages = new Messaging.SingleEmailMessage[] {};
    for (ModelClass m : models) {
        if (m.flag) {
            Messaging.SingleEmailMessage message = new Messaging.SingleEmailMessage();
            message.setTargetObjectId(m.Std.Contacto__r.Id);
            if (String.isNotBlank(emailTemplateId)) {
                message.setTemplateId(emailTemplateId);
            }
            if(attachment.name !=NULL && attachment.Body !=NULL) {
                message.setFileAttachments(fileAttachments);
            } 
            messages.add(message);
        }
    }

    return messages;
}

@TestVisible private static String getEmailTemplateId(String personalize) {
    String result;
    if (personalize == 'Email personalizado')  {        
        result = [SELECT Id FROM EmailTemplate WHERE developername = 'Capacitacion'].Id;
    }
    return result;
}
Notice that the two new helper methods don't require an object (static), have inputs, and easily testable outputs. Your business logic can now be tested much more easily and completely.

Once you've made some design changes so that testing is easier, run your tests in Developer Console or VSCode. In both those places, you can see which lines are not covered by your unit tests. Also, check out some of my blog posts on unit testing (http://force-code.com/reviews-improve-quality-and-supercharge-your-team/) and code reviews (http://force-code.com/reviews-improve-quality-and-supercharge-your-team/).

Best of luck and happy coding!
~Steve Cox
Force-Code, LLC (http://force-code.com/posts/)
author of Salesforce Defect Domination (http://force-code.com/salesforce-defect-domination-a-handbook-for-finding-fixing-and-preventing-defects-in-force-com-development/)
create of SfApexDoc (http://force-code.com/sfapexdoc-in-visual-studio-code/)