2

I have a base class, and a test class with several test methods that are all passing. However, my base class still shows 0% coverage, and I have no idea why.

Here is the base class, which works great.

/**
* @name          ZuoraUsageHandler

* @description   Map Zuora Usage records with their recurring counterpart 
          this call is calling from Trigger of Zuora Usage

* @createddate   17th August 2018
*/

public without sharing class ZuoraUsageHandler extends TriggerHandler {
 public static Boolean isRecurringAfterUpdate = false;

 public override void beforeInsert() {
  if (!isRecurringAfterUpdate) {
   linkZuoraUsage(Trigger.new);
  }
 }

 private static void linkZuoraUsage(List < Zuora_Usage__c > zuoraUsageList) {

  // Compile map of recurring charges and their floor quantities
  Map < String, Decimal > linkedRecurringQuantity = new Map < String, Decimal > ();
  Map < String, String > skuProductfeed = getProductFeed();

  // Process list of Account Ids to pull old counts
  List < Id > accountIds = new List < Id > ();
  for (Zuora_Usage__c zuoraUsage: zuoraUsageList) {
   accountIds.add(zuoraUsage.CRMId__c);
  }
  Map < String, Decimal > oldCountMap = getOldCounts(accountIds);

  // Get 1st day of last month since we bill usage in arrears
  Date currentPeriod = System.today().toStartOfMonth();
  Date chargePeriod = currentPeriod.addMonths(-1);

  // Store the recurring charge floors / quantity
  for (Zuora_Usage__c zuoraUsage: zuoraUsageList) {
   if (zuoraUsage.Charge_Type__c == 'Recurring') {
    linkedRecurringQuantity.put(zuoraUsage.Rate_Plan_ID__c, zuoraUsage.QTY__c);
   }
  }

  // Update the usage charges with the included quantity from the recurring charge based on Rate Plan ID
  // Zuora just reflects 0 for usage charges out of the box
  // IncludedQTY is a custom attribute we provide to customers on their invoices
  for (Zuora_Usage__c zuoraUsage: zuoraUsageList) {
   if (zuoraUsage.Charge_Type__c == 'Usage') {
    zuoraUsage.INCLUDEDQTY__c = linkedRecurringQuantity.get(zuoraUsage.Rate_Plan_ID__c);
    zuoraUsage.product_feed__c = skuProductfeed.get(zuoraUsage.SKU__c);
    zuoraUsage.Old_Count__c = oldCountMap.get(zuoraUsage.CRMId__c + ' - ' + zuoraUsage.product_feed__c);
    zuoraUsage.StartDate__c = chargePeriod;
   }
  }
 }

 private static Map < String, String > getProductFeed() {
  // Used to determine the mapping of ARC to Zuora Charges
  List < Zuora__Product__c > productList = [SELECT Id, Zuora__SKU__c, product_feed__c FROM Zuora__Product__c];

  Map < String, String > skuProductFeed = new Map < String, String > ();

  for (Zuora__Product__c zuoraProduct: productList) {
   skuProductFeed.put(zuoraProduct.Zuora__SKU__c, zuoraProduct.product_feed__c);
  }
  return skuProductFeed;
 }

 private static Map < String, Decimal > getOldCounts(List < Id > accountIds) {
  // Used to snapshot the old count details from the Account record
  Map < String, Decimal > oldCountMap = new Map < String, Decimal > ();

  List < Account > accountList = [SELECT Id, Headcount__c, benefits_headcount__c, payroll_headcount__c, Timesheets__c FROM Account WHERE Id IN: accountIds];

  for (Account a: accountList) {
   if (a.Headcount__c == NULL) {
    oldCountMap.put(a.Id + ' - ' + 'hris_total', 0);
   } else {
    oldCountMap.put(a.Id + ' - ' + 'hris_total', a.Headcount__c);
   }

   if (a.benefits_headcount__c == NULL) {
    oldCountMap.put(a.Id + ' - ' + 'benefits_total', 0);
   } else {
    oldCountMap.put(a.Id + ' - ' + 'benefits_total', a.benefits_headcount__c);
   }

   if (a.payroll_headcount__c == NULL) {
    oldCountMap.put(a.Id + ' - ' + 'payroll_total', 0);
   } else {
    oldCountMap.put(a.Id + ' - ' + 'payroll_total', a.payroll_headcount__c);
   }

   if (a.Timesheets__c == NULL) {
    oldCountMap.put(a.Id + ' - ' + 'timesheets_total', 0);
   } else {
    oldCountMap.put(a.Id + ' - ' + 'timesheets_total', Decimal.valueOf(a.Timesheets__c));
   }

  }
  return oldCountMap;
 }

}

And here is the test class:

@isTest
private class ZuoraUsageHandler_Test {
 @testSetup
 private static void test() {

  Date currentPeriod = System.today().toStartOfMonth();
  Date chargePeriod = currentPeriod.addMonths(-1);

  Account account = (Account) TestFactory.createSObject(new Account(),
   'TestFactory.AccountDefaults');
  // override additional needed account values for legacy counts
  account.Headcount__c = 100;
  account.benefits_headcount__c = 100;
  account.payroll_headcount__c = 100;
  account.Timesheets__c = '100';
  insert account;

  Product_Instance__c testProdInstance = (Product_Instance__c) TestFactory.createSObject(new Product_Instance__c(),
   'TestFactory.ProductInstanceDefaults');
  testProdInstance.Account__c = account.Id;
  insert testProdInstance;

  Product_Usage__c testProdUsage = (Product_Usage__c) TestFactory.createSObject(new Product_Usage__c(),
   'TestFactory.ProductUsageDefaults');
  testProdUsage.Product_Instance__c = testProdInstance.Id;
  // Override start period to align with zuora usage
  testProdUsage.Date__c = chargePeriod;

  insert testProdUsage;

  // create list of product feeds for creating pairs of zuora usage records
  String[] productFeeds = new List<String>();
  productFeeds.add('hris_total');
  productFeeds.add('payroll_total');
  productFeeds.add('benefits_total');
  productFeeds.add('timesheets_total');

  List < Zuora_Usage__c > zuoraUsageTestRecords = new List < Zuora_Usage__c > ();

  // Setup 4 usage based charges
  for (Integer i = 0; i < 4; i++) {
   Zuora_Usage__c zuoraUsageRecord = new Zuora_Usage__c(
    Charge_Type__c = 'Usage',
    StartDate__c = chargePeriod,
    Rate_Plan_Id__c = 'alphazur ' + i,
    CRMID__c = account.Id,
    Product_Feed__c = productFeeds[i]
   );
   zuoraUsageTestRecords.add(zuoraUsageRecord);
  }


  // Setup 4 recurring based charges
  for (Integer i = 0; i < 4; i++) {
   Zuora_Usage__c zuoraUsageRecord = new Zuora_Usage__c(
    Charge_Type__c = 'Recurring',
    StartDate__c = chargePeriod,
    Rate_Plan_Id__c = 'alphazur ' + i,
    CRMID__c = account.Id,
    QTY__c = 100,
    Product_Feed__c = productFeeds[i]
   );
   zuoraUsageTestRecords.add(zuoraUsageRecord);
  }
 }
 @isTest
 static void testGetProductFeed() {
  Test.startTest();
  List < Zuora__Product__c > productList = [SELECT Id, Zuora__SKU__c, product_feed__c FROM Zuora__Product__c];
  List < Zuora_Usage__c > zuoraUsageRecords = [SELECT Id, Charge_Type__c, StartDate__c, QTY__c, Rate_Plan_Id__c, SKU__c, INCLUDEDQTY__c, Old_Count__c, CRMID__c FROM Zuora_Usage__c];

  Map < String, String > skuProductFeed = new Map < String, String > ();
  for (Zuora__Product__c product: productList) {
   skuProductFeed.put(product.Zuora__SKU__c, product.product_feed__c);
  }

  for (Zuora_Usage__c zuoraUsageRecord: zuoraUsageRecords) {
   // check to see if Map contains sku as a value, if so assert the product_feed__c value is the same
   // @todo add if statement
   System.assertEquals(zuoraUsageRecord.product_feed__c, skuProductFeed.get(zuoraUsageRecord.SKU__c));
  }
   Test.stopTest();
 }


@isTest
static void testGetOldCounts() {
 Test.startTest();
 // Create map of accounts and their corresponding legacy counts
 Map < String, Decimal > oldCountMap = new Map < String, Decimal > ();

 List < Account > accountList = [SELECT Id, Headcount__c, benefits_headcount__c, payroll_headcount__c, Timesheets__c FROM Account];

 for (Account a: accountList) {
  if (a.Headcount__c == NULL) {
   oldCountMap.put(a.Id + ' - ' + 'hris_total', 0);
  } else {
   oldCountMap.put(a.Id + ' - ' + 'hris_total', a.Headcount__c);
  }

  if (a.benefits_headcount__c == NULL) {
   oldCountMap.put(a.Id + ' - ' + 'benefits_total', 0);
  } else {
   oldCountMap.put(a.Id + ' - ' + 'benefits_total', a.benefits_headcount__c);
  }

  if (a.payroll_headcount__c == NULL) {
   oldCountMap.put(a.Id + ' - ' + 'payroll_total', 0);
  } else {
   oldCountMap.put(a.Id + ' - ' + 'payroll_total', a.payroll_headcount__c);
  }

  if (a.Timesheets__c == NULL) {
   oldCountMap.put(a.Id + ' - ' + 'timesheets_total', 0);
  } else {
   oldCountMap.put(a.Id + ' - ' + 'timesheets_total', Decimal.valueOf(a.Timesheets__c));
  }
 }

 List < Zuora_Usage__c > zuoraUsageRecords = [SELECT Id, Charge_Type__c, StartDate__c, QTY__c, Rate_Plan_Id__c, SKU__c, INCLUDEDQTY__c, Old_Count__c, CRMID__c, Usage_Key__c FROM Zuora_Usage__c WHERE Charge_Type__c = 'Usage'];

 // Validate that the old counts match based on the Usage Key 
 for (Zuora_Usage__c zuoraUsageRecord: zuoraUsageRecords) {
  System.assertEquals(zuoraUsageRecord.Old_Count__c, oldCountMap.get(zuoraUsageRecord.Usage_Key__c));
 }
 Test.stopTest();
}

@isTest
static void testLinking() {
 Test.startTest();
 // Need a list of usage records, rate_plan_id and included quantity
 // Need a list of recurring records, id and quantity
 List < Zuora_Usage__c > zuoraUsageRecords = [SELECT Id, Charge_Type__c, StartDate__c, QTY__c, Rate_Plan_Id__c, SKU__c, INCLUDEDQTY__c, Old_Count__c, CRMID__c, Usage_Key__c FROM Zuora_Usage__c WHERE Charge_Type__c = 'Usage'];
 List < Zuora_Usage__c > zuoraRecurringRecords = [SELECT Id, Charge_Type__c, StartDate__c, QTY__c, Rate_Plan_Id__c, SKU__c, INCLUDEDQTY__c, Old_Count__c, CRMID__c, Usage_Key__c FROM Zuora_Usage__c WHERE Charge_Type__c = 'Recurring'];

 // Stored map of the recurring charges
 Map < String, Decimal > recurringMap = new Map < String, Decimal > ();
 for (Zuora_Usage__c recurringCharge: zuoraRecurringRecords) {
  recurringMap.put(recurringCharge.Rate_Plan_Id__c, recurringCharge.QTY__c);
 }
  Date currentPeriod = System.today().toStartOfMonth();
  Date chargePeriod = currentPeriod.addMonths(-1);

 // Validate that the usage charges have the correct recurring quantity
 for (Zuora_Usage__c usageCharge: zuoraUsageRecords) {
  System.assertEquals(usageCharge.INCLUDEDQTY__c, recurringMap.get(usageCharge.Rate_Plan_Id__c));
  System.assertEquals(usageCharge.StartDate__c, chargePeriod);
 }

 Test.stopTest();
}
}

When I run the Test class in the Developer Console, I have the "Always Run Asynchronously" checkbox set to TRUE. Any idea what I'm doing wrong? I should also make mention that I'm calling the base class from a before insert trigger on the Zuora_Usage__c object.

Any help would be greatly appreciated.

1 Answer 1

4

You didn't insert the zuoraUsageTestRecords records, so there wasn't any coverage. Your test ran fine, because you forgot to check how many records you were actually processing against, and all of your code didn't catch it because iterating over empty query lists is allowed, and DML operations on zero records is also allowed.

1
  • 3
    @TomKline No problem! Sometimes we just need a second pair of eyes.
    – sfdcfox
    Aug 22, 2018 at 19:26

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.