[SalesForce] test class is not covering email messaging

trigger:

trigger TaskCompletion on Task (after insert,after update){ 
   IF(trigger.isinsert){
   for (Task E : Trigger.new){ 
         If((E.CreatedById != E.OwnerId)&&(E.Notification_on_Completion__c !=false)){
                User U= [select id,Email,Name from user where id =:E.CreatedById ];
                User U1= [select id,Email,Name from user where id =:E.OwnerId];
                Task EE = [Select What.Name,Who.Name from task where id = :E.Id]; 
                Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
                String[] toAddresses = new String[] {U.Email};  
                mail.setToAddresses(toAddresses);                   
                mail.setSubject('Status of the Task' );                 
                mail.setPlainTextBody('Hi'+' '+U.Name +',' + '\n\n ' +'The task assigned to'+' '+U1.Name+' '+'is'+' '+E.Status+'.' 
                +'Details are below.'+'\n\n'+'Subject :'+' '+E.Subject+'\n'+'Comments :'+' '+E.Description+'\n'+'Related To :'+' '+EE.What.Name+'\n'+'Name :'+' '+
                EE.Who.Name+'\n'+'URL Link : https://ap1.salesforce.com/'+ E.Id +'\n\n'+'Regards,'+'\n'+'Admin.' );
                Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail }); 
        }

     }}
     IF(trigger.isupdate){
   for (Task E : Trigger.new){ 
         If((E.CreatedById != E.OwnerId)&&(E.Notification_on_Completion__c !=false)&&(trigger.oldmap.get(E.id).status!=trigger.newmap.get(E.id).status)){
                User U= [select id,Email,Name from user where id =:E.CreatedById ];
                User U1= [select id,Email,Name from user where id =:E.OwnerId];
                Task EE = [Select What.Name,Who.Name from task where id = :E.Id]; 
                Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
                String[] toAddresses = new String[] {U.Email};  
                mail.setToAddresses(toAddresses);                   
                mail.setSubject('Status of the Task' );                 
                mail.setPlainTextBody('Hi'+' '+U.Name +',' + '\n\n ' +'The task assigned to'+' '+U1.Name+' '+'is'+' '+E.Status+'.' 
                +'Details are below.'+'\n\n'+'Subject :'+' '+E.Subject+'\n'+'Comments :'+' '+E.Description+'\n'+'Related To :'+' '+EE.What.Name+'\n'+'Name :'+' '+
                EE.Who.Name+'\n'+'URL Link : https://ap1.salesforce.com/'+ E.Id +'\n\n'+'Regards,'+'\n'+'Admin.' );
                Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail }); 
        }

     }}
}

test case:

@IsTest
private class TestTaskCompletion{
     static testmethod void TestTaskCompletion (){    
           Profile pf = [Select Id from Profile where Name = 'Standard User_1'];
             User u = new User();
                //u.FirstName = 'Test';
                u.LastName = 'Nicomatic2';
                u.Email = 'test@gmail.com.sandbox';
                u.CompanyName = 'test.com';
                u.Title = 'Test User';
                u.Username = 'test@gmail.com.sandbox';
                u.Alias = 'ni';
                u.CommunityNickname = 'ni';
                u.TimeZoneSidKey = 'America/Mexico_City';
                u.LocaleSidKey = 'en_US';
                u.EmailEncodingKey = 'ISO-8859-1';
                u.ProfileId = pf.Id;
                u.LanguageLocaleKey = 'en_US';       
                insert u;

           User u1 = new User();
                //u.FirstName = 'Test';
                u1.LastName = 'Nicomatic22';
                u1.Email = 'test1@gmail.com.sandbox';
                u1.CompanyName = 'tes1t.com';
                u1.Title = 'Test User1';
                u1.Username = 'test1@gmail.com.sandbox';
                u1.Alias = 'ni1';
                u1.CommunityNickname = 'ni1';
                u1.TimeZoneSidKey = 'America/Mexico_City';
                u1.LocaleSidKey = 'en_US';
                u1.EmailEncodingKey = 'ISO-8859-1';
                u1.ProfileId = pf.Id;
                u1.LanguageLocaleKey = 'en_US';       
                insert u1;

            System.runAs(u){
             Task t = New Task(Subject='test',Priority='Normal',Status='Completed',Notification_on_Completion__c=true);
                  Insert t;
             Task tt =[select id,CreatedById,OwnerId from task where Id =:t.Id];
             Task t1 = New Task(Subject='test',Priority='Normal',Status='Not started' );
                t1.OwnerId = u.Id;
               insert t1;

          }
         system.runas(u1){
                       Task t1 = New Task(Subject='test',Priority='Normal',Status='Not started' );
                t1.OwnerId = u1.Id;
               insert t1;
           t1.status='Need identified' ;
              update t1;
              system.assertequals(t1.status,'Need identified')  ;  
               emailmessage em = new emailmessage();
                em.fromaddress = 'Test@test.com';
                em.toaddress = 'test1@test.com';
                em.subject = 'Test Email';
                em.textbody = 'testing';
                em.parentid = t1.id;
                test.starttest();
                insert em;
                test.stoptest();  
          }
     }
}

I am not getting code coverage for messaging

 Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
                    String[] toAddresses = new String[] {U.Email};  
                    mail.setToAddresses(toAddresses);                   
                    mail.setSubject('Status of the Task' );                 
                    mail.setPlainTextBody('Hi'+' '+U.Name +',' + '\n\n ' +'The task assigned to'+' '+U1.Name+' '+'is'+' '+E.Status+'.' 
                    +'Details are below.'+'\n\n'+'Subject :'+' '+E.Subject+'\n'+'Comments :'+' '+E.Description+'\n'+'Related To :'+' '+EE.What.Name+'\n'+'Name :'+' '+
                    EE.Who.Name+'\n'+'URL Link : https://ap1.salesforce.com/'+ E.Id +'\n\n'+'Regards,'+'\n'+'Admin.' );
                    Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail }); 

Help me to get the 100% code coverage

Thanks in advance

Best Answer

It is hard to tell but it appears that most of the code is duplicated between the insert and update cases. One solution to that would be to move most of the code out to a separate class, but in this case this sort of refactoring might be appropriate:

trigger TaskCompletion on Task (after insert, after update) {
    // Do all queries on User here based on sets of IDs obtained from Trigger.new
    Messaging.SingleEmailMessage[] emails = new Messaging.SingleEmailMessage[] {};
    for (Task t : Trigger.new) {
        if (t.CreatedById != t.OwnerId && !t.Notification_on_Completion__c) {
            // On insert or status change only
            if(Trigger.isInsert || E.Status != Trigger.oldMap.get(t.Id).Status) {
                // Add email to emails
            }
        }
    }
    Messaging.sendEmail(emails);
}

A problem with the test is that you are not changing the owner (in both cases):

system.runas(u1) {
    // Makes the owner u1 (the runAs User)
    Task t1 = New Task(Subject='test',Priority='Normal',Status='Not started');
    // Instead of u1.Id this should be u.Id...
    t1.OwnerId = u1.Id;
    t1.status='Need identified' ;
    update t1;

A final point is that as emails are not sent in tests asserting what has happened is awkward; one way around that is to create a class that the trigger uses to send:

public class Emails {
    @TestVisible
    private Messaging.SingleEmailMessage[] sent; 
    public void sendEmail(Messaging.SingleEmailMessage[] emails) {
        Messaging.sendEmail(emails);
        sent = emails;
    }
}

and the test can assert about the Emails.sent content.

Related Topic