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
MohiniMohini 

I want a to write a test class with 75% coverage .

The batch apex is sending account details as attachment and sending email and the test class is only covering 37% .Please helo me to get 75% code coverage
Apex Class:
global class UserReport implements Database.Batchable<SObject>, Database.AllowsCallouts, Database.Stateful {
  global  blob MyBlob;
   public List<String> searchstring = new List<String> {'Sales Manager','Sales User'};
    private List<String> fieldNames = new List<String> {
        'Id', 'Name', 'Registry_ID_EBS__c','OwnerId', 'Owner.Email', 'Owner.IsActive'
    };
      
     global String csvContent = '';
                
    global Database.QueryLocator start(Database.BatchableContext context) {
        return Database.getQueryLocator([Select Id, Name, Registry_ID_EBS__c, OwnerId, Owner.Email, Owner.IsActive,Owner.profile.Name From Account where Owner.profile.Name IN ('Sales Manager', 'Sales User') ]);
    }
    
    global void execute(Database.BatchableContext context, List<Account> records) {
        Map<Id, User> owners = new Map<Id, User>();
        for (Account record : records) {
            owners.put(record.OwnerId, null);
        }
        owners.remove(null);
        owners.putAll([Select Id, Name, Email, IsActive From User Where Id IN :owners.keySet()]);
        
       
        for (String fieldName : fieldNames) {
            if (fieldName == 'OwnerId') {
                csvContent += '"Owner Name",';
            } else if (fieldName == 'Owner.Email') {
                csvContent += '"Owner Email",';
            } else if (fieldName == 'Owner.IsActive') {
                csvContent += '"Owner Active",';
            } else {
                csvContent += '"' + fieldName + '"' + ',';
            }
        }
        csvContent += '\n';
        for (Account record : records) {
            for (String fieldName : fieldNames) {
                if (fieldName == 'OwnerId') {
                    String ownerName = '';
                    if (record.OwnerId != null && owners.containsKey(record.OwnerId)) {
                        ownerName = String.valueOf(owners.get(record.OwnerId).Name).replace('"', '""');
                    }
                    csvContent += '"' + ownerName + '"' + ',';
                } else if (fieldName == 'Owner.Email') {
                    String ownerEmail = '';
                    if (record.OwnerId != null && owners.containsKey(record.OwnerId)) {
                        ownerEmail = String.valueOf(owners.get(record.OwnerId).Email).replace('"', '""');
                    }
                    csvContent += '"' + ownerEmail + '"' + ',';
                } else if (fieldName == 'Owner.IsActive') {
                    String ownerIsActive = '';
                    if (record.OwnerId != null && owners.containsKey(record.OwnerId)) {
                        ownerIsActive = String.valueOf(owners.get(record.OwnerId).IsActive).replace('"', '""');
                    }
                    csvContent += '"' + ownerIsActive + '"' + ',';
                } else {
                    Object fieldValueObj = record.get(fieldName);
                    if (fieldValueObj != null) {
                        String fieldValue = String.valueOf(fieldValueObj).replace('"', '""');
                        csvContent += '"' + fieldValue + '"' + ',';
                    } else {
                        csvContent += ',';
                    }
                }
            }
            csvContent += '\n';
           //system.debug('csvContent'+csvContent);
        }
        MyBlob = blob.valueOf(csvContent); 
          system.debug('MyBlob1'+MyBlob);

    }

   global void finish(Database.BatchableContext context) {
        system.debug('MyBlob2'+MyBlob);
    String emailAddress1 = 'selvin.paul@continuserve.com';
    Messaging.EmailFileAttachment csvAttachment = new Messaging.EmailFileAttachment();
    String myName = 'AccountList.csv';
    csvAttachment.setFileName(myName);
    csvAttachment.setBody(MyBlob);
       csvAttachment.setContentType('application/csv');
       system.debug('ss'+MyBlob);
    Messaging.SingleEmailMessage myEmail = new Messaging.SingleEmailMessage();
    String[] toAddresses = new String[]{emailAddress1};
    String subject = 'UserID and List CSV';
    myEmail.setSubject(subject);
    myEmail.setToAddresses(toAddresses);
    myEmail.setPlainTextBody('User Alias Report');
    myEmail.setHtmlBody('Hi All'+','+'</br><br/>'+ 'Please find attached the sales user detail report from Salesforce production CRM.' +'</br><br/'+'Thanks'+','+'</br>'+'Brinks Team');
   Messaging.EmailFileAttachment[] attachments = new Messaging.EmailFileAttachment[]{csvAttachment};
myEmail.setFileAttachments(attachments);

    Messaging.SendEmailResult[] r = Messaging.sendEmail(new Messaging.SingleEmailMessage[]{myEmail});
}
}
Test Class:

@isTest
public class UserReportTest {
static String str = 'Name,Registry_ID_EBS__c,OwnerId,Owner.Email,Owner.IsActive \n';       

    public static String[] csvFileLines;
    public static Blob csvFileBody;

    static testmethod void testfileupload(){
        Test.startTest();       
        csvFileBody = Blob.valueOf(str);
        String csvAsString = csvFileBody.toString();
        csvFileLines = csvAsString.split('\n'); 

       UserReport result = new UserReport();
       
       // result .csvAttachment();
        Test.stopTest();
    } 

    static testmethod void testfileuploadNegative(){
        Test.startTest();       
        csvFileBody = Blob.valueOf(str);
        String csvAsString = csvFileBody.toString();
        csvFileLines = csvAsString.split('\n'); 

     UserReport result = new UserReport();
       Id batchJobId = Database.executeBatch(new UserReport(), 200);
        Test.stopTest();
    }
}
SwethaSwetha (Salesforce Developers) 
HI Mohini,
Can you include which lines of UserReport class are uncovered in the test class? Thanks
MohiniMohini
Thanks for replying Swetha. The complete execute method is not getting covered


  global void execute(Database.BatchableContext context, List<Account> records) {
        Map<Id, User> owners = new Map<Id, User>();
        for (Account record : records) {
            owners.put(record.OwnerId, null);
        }
        owners.remove(null);
        owners.putAll([Select Id, Name, Email, IsActive From User Where Id IN :owners.keySet()]);
        
       
        for (String fieldName : fieldNames) {
            if (fieldName == 'OwnerId') {
                csvContent += '"Owner Name",';
            } else if (fieldName == 'Owner.Email') {
                csvContent += '"Owner Email",';
            } else if (fieldName == 'Owner.IsActive') {
                csvContent += '"Owner Active",';
            } else {
                csvContent += '"' + fieldName + '"' + ',';
            }
        }
        csvContent += '\n';
        for (Account record : records) {
            for (String fieldName : fieldNames) {
                if (fieldName == 'OwnerId') {
                    String ownerName = '';
                    if (record.OwnerId != null && owners.containsKey(record.OwnerId)) {
                        ownerName = String.valueOf(owners.get(record.OwnerId).Name).replace('"', '""');
                    }
                    csvContent += '"' + ownerName + '"' + ',';
                } else if (fieldName == 'Owner.Email') {
                    String ownerEmail = '';
                    if (record.OwnerId != null && owners.containsKey(record.OwnerId)) {
                        ownerEmail = String.valueOf(owners.get(record.OwnerId).Email).replace('"', '""');
                    }
                    csvContent += '"' + ownerEmail + '"' + ',';
                } else if (fieldName == 'Owner.IsActive') {
                    String ownerIsActive = '';
                    if (record.OwnerId != null && owners.containsKey(record.OwnerId)) {
                        ownerIsActive = String.valueOf(owners.get(record.OwnerId).IsActive).replace('"', '""');
                    }
                    csvContent += '"' + ownerIsActive + '"' + ',';
                } else {
                    Object fieldValueObj = record.get(fieldName);
                    if (fieldValueObj != null) {
                        String fieldValue = String.valueOf(fieldValueObj).replace('"', '""');
                        csvContent += '"' + fieldValue + '"' + ',';
                    } else {
                        csvContent += ',';
                    }
                }
            }
            csvContent += '\n';
           //system.debug('csvContent'+csvContent);
        }
        MyBlob = blob.valueOf(csvContent); 
          system.debug('MyBlob1'+MyBlob);

    }
Yathansh SharmaYathansh Sharma

Hi Mohini,

Your batch class has a query filtering on the Profile name as 'Sales Manager' and 'Sales User'. Due to this when you execute the method from the test class, it is not picking up any records, hence it is not entering the execute method. Execute method is called only when there is at least 1 record to process as part of the batch.

In your scenario, create a new user inside the test class only with either the profile as 'Sales Manager' or 'Sales User' and then create new accounts keeping the users as the owner.

Test class cannot access org data unless we specify using (SeeAllData=True), which is highly discouraged when considering the best practices. So for test class purposes, it is best to recreate new data which will not be saved to the org and then run the test on those records.

MohiniMohini
No luck...

@isTest (SeeAllData=true)

 public class TestUserReport {
    static String str = 'Name,Registry_ID_EBS__c,OwnerId,Owner.Email,Owner.IsActive \n';       

    public static String[] csvFileLines;
    public static Blob csvFileBody;

     @testSetup static void UserAccountReport ()
     {
   
  
               
  // Taking just the User
        
        User owner = new User(
        FirstName='Kevin',
        LastName='Martin',
        Email ='kevin.martin@test.com',
        ProfileId ='Sales Manager',
        IsActive  = true
        );
        insert owner;
     
            // Taking just the account
   
       Account acc = new Account(
       Name = 'Test Temp Account',
       Id = '6789',
       AccountNumber='3456789',
       Registry_ID_EBS__c  ='8989'
       );
       insert acc; 
                   
     
        
        Test.startTest();
        UserReport obj = new UserReport();
        DataBase.executeBatch(obj); 
        Test.stopTest();
         
        //Verify accounts updated
        List<Account> accList = [Select Id, Name, Registry_ID_EBS__c, OwnerId, Owner.Email, Owner.IsActive,Owner.profile.Name From Account  ];
        System.assert(accList[0].Name.Contains('Updated'));
    }
      static testmethod void testfileupload(){
        Test.startTest();       
        csvFileBody = Blob.valueOf(str);
        String csvAsString = csvFileBody.toString();
        csvFileLines = csvAsString.split('\n'); 

       UserReport result = new UserReport();
       
       // result .csvAttachment();
        Test.stopTest();
    } 

    static testmethod void testfileuploadNegative(){
        Test.startTest();       
        csvFileBody = Blob.valueOf(str);
        String csvAsString = csvFileBody.toString();
        csvFileLines = csvAsString.split('\n'); 

     UserReport result = new UserReport();
       Id batchJobId = Database.executeBatch(new UserReport(), 200);
        Test.stopTest();
    }
}
SwethaSwetha (Salesforce Developers) 
Basically the idea is 

>> The test class needs to create test data that will be used in the start() and execute() methods. This test data should include Accounts owned by users with the profile names "Sales Manager" and "Sales User", since these are the profiles that are being queried in the start() method.

>> The test class should also make assertions on the CSV content that is generated in the execute() method to ensure that the correct data is being output.

>>The finish() method is also being executed as part of the batch job, so the test class should include assertions for this method as well.

Try below snippet to get started
@isTest
private class UserReportTest {

    @isTest
    static void testUserReport() {
        // Create test data
        Profile testProfile = new Profile(Name = 'Test Profile');
        insert testProfile;
        
        User testUser1 = new User(
            Username = 'testuser1@example.com',
            Email = 'testuser1@example.com',
            Alias = 'testuser1',
            LastName = 'Test',
            FirstName = 'User 1',
            ProfileId = testProfile.Id,
            IsActive = true
        );
        insert testUser1;
        
        User testUser2 = new User(
            Username = 'testuser2@example.com',
            Email = 'testuser2@example.com',
            Alias = 'testuser2',
            LastName = 'Test',
            FirstName = 'User 2',
            ProfileId = testProfile.Id,
            IsActive = true
        );
        insert testUser2;
        
        Account testAccount1 = new Account(
            Name = 'Test Account 1',
            Registry_ID_EBS__c = '12345',
            OwnerId = testUser1.Id
        );
        insert testAccount1;
        
        Account testAccount2 = new Account(
            Name = 'Test Account 2',
            Registry_ID_EBS__c = '67890',
            OwnerId = testUser2.Id
        );
        insert testAccount2;
        
        // Call batch class
        Test.startTest();
        UserReport batch = new UserReport();
        Database.executeBatch(batch);
        Test.stopTest();
        
        // Assert that email was sent
        List<Messaging.SingleEmailMessage> sentEmails = [SELECT Id FROM Messaging.SingleEmailMessage];
        System.assertEquals(1, sentEmails.size());
        
        // Assert email contents
        Messaging.SingleEmailMessage email = sentEmails[0];
        System.assertEquals('UserID and List CSV', email.getSubject());
        System.assertEquals('selvin.paul@continuserve.com', email.getToAddresses()[0]);
        System.assertEquals('Hi All,<br/><br/>Please find attached the sales user detail report from Salesforce production CRM.<br/><br/>Thanks,<br/>Brinks Team', email.getHtmlBody());
        System.assertEquals(1, email.getFileAttachments().size());
        Messaging.EmailFileAttachment attachment = email.getFileAttachments()[0];
        System.assertEquals('AccountList.csv', attachment.getFileName());
        System.assertEquals('application/csv', attachment.getContentType());
        
        // Assert CSV contents
        String csvContent = attachment.getBody().toString();
        System.assertEquals('"Id","Name","Registry_ID_EBS__c","Owner Name","Owner Email","Owner Active"' + '\n'
                            + '"' + testAccount1.Id + '","Test Account 1","12345","User 1","testuser1@example.com","true"' + '\n'
                            + '"' + testAccount2.Id + '","Test Account 2","67890","User 2","testuser2@example.com","true"' + '\n', csvContent);
    }

}

If this information helps, please mark the answer as best. Thank you

MohiniMohini
Hi Swetha , 
Thanks for all the help . Please just help me with the error .Attached is the 2 issues coming up .
 User-added image