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
Asel Vazir 1Asel Vazir 1 

Test Class for Apex Batch Job generating Invoices covers only 38%

Please help me to finish my Test Class for the following Batch Job generating Invoice creation.

Batch Job
global class InvoiceGenerateBatchJob implements Database.Batchable<SObject> {

    global Database.QueryLocator start(Database.BatchableContext BC) {


        return Database.getQueryLocator([
                SELECT Name, Id, Rent_Due_Date__c, Monthly_Rate__c, Property__c
                FROM Tenant__c
                WHERE Rent_Due_Date__c = TODAY
        ]);
    }

    global void execute(Database.BatchableContext BC, List<Tenant__c> tenants) {

        List<Invoice__c> invoices = new List<Invoice__c>();

        for (Tenant__c tenant : tenants) {
            for(Invoice__c invoice : invoices){

                invoice.Bill_To_Tenant__c = tenant.Name;
                invoice.Due_Date__c = tenant.Rent_Due_Date__c;
                invoices.add(invoice);
            }
        }
        insert invoices;
    }

    global void finish(Database.BatchableContext BC) {

        AsyncApexJob job = [SELECT Id, Status, NumberOfErrors, JobItemsProcessed,TotalJobItems, CreatedBy.Email
                            FROM AsyncApexJob
                            WHERE Id = :BC.getJobId()];
    }

}
Scheduler Class For Batch Apex
global class InvoiceGenerateBatchScheduled implements Schedulable {
    global void execute(SchedulableContext sc) {
        InvoiceGenerateBatchJob invBatch = new InvoiceGenerateBatchJob();
        Database.executeBatch(invBatch, 200);

    }
}

​​​​​​Testing Batch Apex Job and Scheduler Classes:
@IsTest
private class InvoiceGenerateBatchTest {

    @TestSetup
    static void setupData() {

        Property__c property = new Property__c();
        property.Name = 'Prop1';
        property.Business__c = 'Gov';
        insert property;

        List<Tenant__c> tenants = new List<Tenant__c>();
        for (Integer i = 1; i < 5; i++);{

            try {
                Tenant__c t = new Tenant__c();
                t.Name = 'TenOne';
                t.Property__c = [
                        SELECT Id
                        FROM Property__c
                        WHERE Name = 'Prop1'
                        LIMIT 5
                ].Id;
                tenants.add(t);
            } catch (Exception e) {

                insert tenants;
            }
        }
    }

    @IsTest
     static void testInvoiceGenerateBatch() {

     String CRON_EXP = '0 0 22 30 3 ?';
     Date dueDate = Date.today();

     Test.startTest();

     String jobId = System.schedule('CreateInvoice', CRON_EXP, new InvoiceGenerateBatchScheduled());
     Database.executeBatch(new InvoiceGenerateBatchJob());

     Test.stopTest();

     System.assertEquals(5, [SELECT COUNT() FROM Invoice__c WHERE Bill_To_Tenant__r.Name = 'TenOne']);

        }
    }

 
Asel Vazir 1Asel Vazir 1
Here is the updated Test Class with Invoice records
@TestSetup
static void setupData() {

    List<Property__c> prop = new List<Property__c>();
    Property__c property = new Property__c();
    property.Name = 'Prop1';
    property.Business__c = 'Gov';
    prop.add(property);
    insert prop;

    List<Tenant__c> ten = new List<Tenant__c>();
    Tenant__c tenant = new Tenant__c();
    tenant.Name = 'TenOne';
    tenant.Rent_Due_Date__c = System.today();
    tenant.Property__c = property.Id;
    ten.add(tenant);
    insert ten;

    List<Invoice__c> inv = new List<Invoice__c>();
    Invoice__c invoice = new Invoice__c();
    invoice.Bill_To_Tenant__c = tenant.Id;
    invoice.Due_Date__c = tenant.Rent_Due_Date__c;
    inv.add(invoice);
    insert inv;

    }

@IsTest
 static void testInvoiceGenerateBatch() {

 String CRON_EXP = '0 0 23 30 3 ?';
 Date dueDate = Date.today();

 Test.startTest();

 String jobId = System.schedule('CreateInvoice', CRON_EXP, new InvoiceGenerateBatchScheduled());
 Database.executeBatch(new InvoiceGenerateBatchJob());

 Test.stopTest();

 System.assertEquals(1, [SELECT COUNT() FROM Invoice__c WHERE Bill_To_Tenant__r.Name = 'TenOne']);

    }
}

 
sachinarorasfsachinarorasf
Hi Asel Vazir 1,

You can Update your test class code like below to get the desired code coverage.

@IsTest
private class InvoiceGenerateBatchTest {

    @TestSetup
    static void setupData() {

        Property__c property = new Property__c();
        property.Name = 'Prop1';
        insert property;

        List<Tenant__c> tenants = new List<Tenant__c>();
        for (Integer i = 1; i < 5; i++);{

            try {
                Tenant__c t = new Tenant__c();
                t.Name = 'TenOne';
                t.Property__c = [
                        SELECT Id
                        FROM Property__c
                        WHERE Name = 'Prop1'
                        LIMIT 5
                ].Id;
                t.Rent_Due_Date__c  =  date.today();
                tenants.add(t);
                 insert tenants;
            } catch (Exception e) {

               
            }
        }
    }

    @IsTest
     static void testInvoiceGenerateBatch() {

     String CRON_EXP = '0 0 22 30 3 ?';
     Date dueDate = Date.today();

     Test.startTest();

     String jobId = System.schedule('CreateInvoice', CRON_EXP, new InvoiceGenerateBatchScheduled());
     Database.executeBatch(new InvoiceGenerateBatchJob());

     Test.stopTest();

     //System.assertEquals(5, [SELECT COUNT() FROM Invoice__c WHERE Bill_To_Tenant__r.Name = 'TenOne']);

        }
    }

I hope you find the above solution helpful. If it does, please mark as Best Answer to help others too.

Thanks and Regards,
Sachin Arora
www.sachinsf.com
Asel Vazir 1Asel Vazir 1
Hi Sachin,

Thank you for your input. I've tried it and it didn't work though. As you've already seen I've updated the test class and it worked but covered only 76% right now. Was thinking if it always has to be 100% coverage. I know that apex test class should cover at least 75%, but the more it covers the better. Or am I wrong?