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
Swetha S415Swetha S415 

Advanced apex specialist Badge 8 - Create Unit Test

Hello Everyone,
Struggling with step 8 in Advanced apex specialist since a week. Could you please help me out what was the issue and fix that.

Product2Extension:

Public without sharing class Product2Extension {
   
    public List<productWrapper> productsToInsert {get;set;}
    public Product2Extension(ApexPages.StandardController controller){
        productsToInsert = new List<productWrapper>();         
        AddRows();  
    }
    //Get select list options//    
    public List<SelectOption> GetFamilyOptions() {
        List<SelectOption> options = new List<SelectOption>{new SelectOption(Constants.SELECT_ONE, Constants.SELECT_ONE)};
                    for (Schema.PicklistEntry ple : Constants.PRODUCT_FAMILY) {
                        options.add(new SelectOption(ple.getValue(), ple.getLabel()));
                    }
        return options;
    }
    public void AddRows(){
        for ( Integer i=0; i<Constants.DEFAULT_ROWS; i++ ){
            productsToInsert.add( new ProductWrapper() );
        }
    }
   
    public List<ChartHelper.ChartData> GetInventory(){
        return ChartHelper.GetInventory();
    }
   
    public PageReference Save(){
        Savepoint sp = Database.setSavepoint();
        try {
            List<Product2> products = new List<Product2>();
            List<PricebookEntry> entries = new List<PricebookEntry>();
            for (ProductWrapper wrp : productsToInsert){
                if(null!=wrp.productRecord && null!=wrp.pricebookEntryRecord){
                    if(null!=wrp.productRecord.Name && null!=wrp.productRecord.Family && constants.SELECT_ONE!=wrp.productRecord.Family
                       && null!=wrp.productRecord.Initial_Inventory__c && null!=wrp.pricebookEntryRecord.UnitPrice){
                           products.add(wrp.productRecord);
                           PricebookEntry entry=wrp.pricebookEntryRecord;
                           entry.IsActive=true;
                           system.debug('=======454545===='+constants.STANDARD_PRICEBOOK_ID);
                           entry.Pricebook2Id=constants.STANDARD_PRICEBOOK_ID;
                           entries.add(entry);  
                       }
                }
            }
            insert products;           
            for (integer itr=0; itr<entries.size();itr++){
                entries[itr].Product2Id=products[itr].id;
            }
            Database.SaveResult[] srList = Database.insert(entries, false);
            system.debug('============='+srList);
            //insert entries;
            //If successful clear the list and display an informational message
            apexPages.addMessage(new ApexPages.message(ApexPages.Severity.INFO,productsToInsert.size()+' Inserted'));
            productsToInsert.clear();   //Do not remove
            addRows();  //Do not remove
        } catch (Exception e){
            Database.rollback(sp);
           
            apexPages.addMessage(new ApexPages.message(ApexPages.Severity.ERROR,constants.ERROR_MESSAGE));
        }
        return null;
    }
   
    public class ProductWrapper{
        public product2 productRecord {get;set;}
        public pricebookEntry pricebookEntryRecord{get;set;}
        public productWrapper(){
            productRecord = new product2(Initial_Inventory__c =0);
            pricebookEntryRecord = new pricebookEntry(Unitprice=0.0);
        }
    }
}

ProductWrapper:

public class ProductWrapper{
        public product2 productRecord {get;set;}
        public pricebookEntry pricebookEntryRecord{get;set;}
        public productWrapper(){
            productRecord = new product2(Initial_Inventory__c =0);
            pricebookEntryRecord = new pricebookEntry(Unitprice=0.0);
        }
    }

Product2Helper:
public class Product2Helper {
    /**
* @name COLLABORATION_GROUP
* @description List of CollaborationGroup used in both business and test logic
**/
    static List<CollaborationGroup> COLLABORATION_GROUP = [
        SELECT Id
        FROM CollaborationGroup
        WHERE Name = :Constants.INVENTORY_ANNOUNCEMENTS
        OR Name = :('TEST '+Constants.INVENTORY_ANNOUNCEMENTS)
        LIMIT 1
    ];   
    /**
* @name afterUpdate
* @description called by product2 Trigger on After Update
* @param List<Product2> newList
* @param List<Product2> oldList
**/
    public static void AfterUpdate(List<Product2> oldList, List<Product2> newList){
        //ToDo: Declare a List of Product2 records named needsAnnouncement
        List<Product2> needsAnnouncement = new List<Product2>();
        //ToDo: Declare a Map of Strings to Inventory_Setting__mdt records
        Map<String, Decimal> invSettingsMap = new Map<String, Decimal>();
        //ToDo: Loop through a query of Inventory_Setting__mdt records and populate the Map with Name as the key
        List<Inventory_Setting__mdt> invSettings = [SELECT Id, DeveloperName, Low_Quantity_Alert__c FROM Inventory_Setting__mdt];
        for (Inventory_Setting__mdt sett : invSettings) {
            invSettingsMap.put(sett.DeveloperName, sett.Low_Quantity_Alert__c);
        }
        //ToDo: Loop through the Products in newList
        // Use the corresponding Inventory Setting record to determine the correct Low Quantity Alert
        // If the Product's Quantity Remaining has been changed to less than the Low Quantity Alert
        //      add it to the needsAnnouncement list
        for (Product2 prod : newList) {
            if (invSettingsMap.containsKey(prod.Family) && prod.Quantity_Remaining__c < invSettingsMap.get(prod.Family)) {
                needsAnnouncement.add(prod);
            }
        }
        //ToDo: Pass records to the postAlerts method
        PostAlerts(needsAnnouncement);
    }
   
    /**
* @name postAlerts
* @description called by product2 Trigger on After Update
* @param List<Product2> productList
**/
    public static void PostAlerts(List<Product2> productList){
        List<ConnectApi.AnnouncementInput> toPost = new List<ConnectApi.AnnouncementInput>();
        for ( Product2 p : productList ){
            // ToDo: Construct a new AnnouncementInput for the Chatter Group so that it:
            // expires in a day
            // does not notify users via email.
            // and has a text body that includes the name of the product followed by the INVENTORY_LEVEL_LOW constant
            ConnectApi.MessageBodyInput mbi = new ConnectApi.MessageBodyInput();
            ConnectApi.TextSegmentInput textSegmentInput = new ConnectApi.TextSegmentInput();
            mbi.messageSegments = new List<ConnectApi.MessageSegmentInput>();
            textSegmentInput.text = p.Name + ' ' +Constants.INVENTORY_LEVEL_LOW;
            mbi.messageSegments.add(textSegmentInput);
            ConnectApi.AnnouncementInput ai = new ConnectApi.AnnouncementInput();
            ai.expirationDate = Date.today().addDays(1);
            ai.sendEmails = true;
            ai.parentId = COLLABORATION_GROUP[0].Id;
            ai.body = mbi;
            toPost.add(ai);
        }
        // ToDo: Create and enqueue an instance of the announcementQueuable class with the list of Products
        AnnouncementQueueable q = new AnnouncementQueueable(toPost);
        // q.toPost = toPost;
        System.enqueueJob(q);
    }
}

OrderHelper:

public without sharing class OrderHelper {
    /**
* @name AfterUpdate
* @description
* @param List<Order> newList
* @param List<Order> oldList
* @return void
**/
    public static List<Double> check =new List<Double>();
    public Static List<Product2> pr;
    public static void AfterUpdate(List<Order> newList, List<Order> oldList){
        Set<Id> orderIds = new Set<Id>();
        for ( Integer i=0; i<newList.size(); i++ ){
            if ( newList[i].Status == Constants.ACTIVATED_ORDER_STATUS && oldList[i].Status == Constants.DRAFT_ORDER_STATUS ){
                orderIds.add(newList[i].Id);
            }
        }
        RollUpOrderItems(orderIds);
    }
    /**
* @name RollUpOrderItems
* @description Given a set of Activated Order ids, query the child Order Items and related Products to calculate Inventory levels
* @param Set<Id> activatedOrderIds
* @return void
**/
    public static void RollUpOrderItems(Set<Id> activatedOrderIds){
        //ToDo: Declare a Map named "productMap" of Ids to Product2 records
        Map<ID,Product2> productMap =new Map<ID,Product2>();
        List<OrderItem> orderId =[Select OrderID,Product2Id from OrderItem where OrderId IN: activatedOrderIds];
        //ToDo: Loop through a query of OrderItems related to the activatedOrderIds
        for(OrderItem o: orderId){
            //ToDo: Populate the map with the Id of the related Product2 as the key and Product2 record as the value
            Product2 p= [select name,Quantity_Ordered__c from Product2 where Id=: o.Product2Id];
            productmap.put(o.Product2Id,p );
        }
        //ToDo: Loop through a query that aggregates the OrderItems related to the Products in the ProductMap keyset
        pr = new List<Product2>();
        AggregateResult[] groupedResults =[select Product2Id ,SUM(Quantity) from OrderItem where Product2Id IN : productMap.keySet() group by Product2Id];
        for(AggregateResult ag: groupedResults){
            Product2 p= productmap.get((Id)ag.get('Product2Id'));
            p.Quantity_Ordered__c =(Double)ag.get('expr0');
            pr.add(p);
            check.add((Double)ag.get('expr0'));
        }
        update pr;
        //ToDo: Perform an update on the records in the productMap
    }
}

Constants:

public class Constants {
    public static final Integer DEFAULT_ROWS = 5;
    public static final String SELECT_ONE = Label.Select_One;
    public static final String INVENTORY_LEVEL_LOW = Label.Inventory_Level_Low;
    public static final List<Schema.PicklistEntry> PRODUCT_FAMILY;
       static {
        Schema.DescribeFieldResult fieldResult = Product2.Family.getDescribe();
        PRODUCT_FAMILY = fieldResult.getPicklistValues();
    }
    public static final String DRAFT_ORDER_STATUS = 'Draft';
    public static final String ACTIVATED_ORDER_STATUS = 'Activated';
    public static final String INVENTORY_ANNOUNCEMENTS = 'Inventory Announcements';
    public static final String ERROR_MESSAGE = 'An error has occurred, please take a screenshot with the URL and send it to IT.';
    public static final Id STANDARD_PRICEBOOK_ID = '01sf4000007hhtPAAQ';
 }



Please help me out to achieve this Badge.
User-added image
Swetha S415Swetha S415
Remaining Test Classes:

TestDataFactory:
/**
* @name TestDataFactory
* @description Contains methods to construct and/or validate commonly used records
**/
public with sharing class TestDataFactory {
  
    /**
* @name ConstructCollaborationGroup
* @description
**/
    public static CollaborationGroup ConstructCollaborationGroup(){
        //ToDo: Ensure this method returns a single Chatter CollaborationGroup
        //    whose Name starts with 'TEST' followed by the INVENTORY_ANNOUNCEMENTS constant
        //    and configured so anyone can join, see and post updates.
        CollaborationGroup myGroup = new CollaborationGroup();
        myGroup.Name='TEST'+ Constants.INVENTORY_ANNOUNCEMENTS;
        myGroup.CollaborationType='Public'; //can be 'Public' or 'Private'                 
        return myGroup;
    }
  
    /**
* @name CreateProducts
* @description Constructs a list of Product2 records for unit tests
**/
  
    /*
public static List<Product2> ConstructProducts(Integer cnt){
//ToDo: Ensure this method returns a list, of size cnt, of uniquely named Product2 records
//  with all the required fields populated
//  and IsActive = true
//  an Initial Inventory set to 10
//  and iterating through the product family picklist values throughout the list.
List<Product2> products=new List<Product2>();
Integer s=0;
for(Integer n=0; n<cnt; n++)
{
if(s==Constants.PRODUCT_FAMILY.size())
s=0;
Product2 p=new Product2();
p.Name='Product1_'+n;
p.Family=Constants.PRODUCT_FAMILY[s].getLabel();
p.Initial_Inventory__c=10;
p.IsActive=true;
//p.Quantity_Ordered__c=Constants.DEFAULT_ROWS;
products.add(p);
s++;
}
return products;
}
*/
    public  static list<product2> ConstructProducts(Integer cnt){
        //ToDo: Ensure this method returns a list, of size cnt, of uniquely named Product2 records
        //  with all the required fields populated
        //  and IsActive = true
        //  an Initial Inventory set to 10
        //  and iterating through the product family picklist values throughout the list.
      
        List<Product2> prods = new List<Product2>();
      
        for(integer i=0;i< cnt;i++)
        {
            Product2 prod = new Product2();
            prod.Name = 'Side' ;
            prod.isActive = true;
            prod.Initial_Inventory__c = 7;
            if(i >= 4 )
                prod.Family = constants.PRODUCT_FAMILY[0].getValue();
            else
                prod.Family = constants.PRODUCT_FAMILY[i].getValue();
            prods.add(prod);
        }
      
      
      
        return prods; 
      
    }
  
    /**
* @name CreatePricebookEntries
* @description Constructs a list of PricebookEntry records for unit tests
**/
    public static List<PriceBookEntry> ConstructPricebookEntries(List<Product2> prods){
        //ToDo: Ensure this method returns a corresponding list of PricebookEntries records
        //  related to the provided Products
        //  with all the required fields populated
        //  and IsActive = true
        //  and belonging to the standard Pricebook
        List<PriceBookEntry> listPBE=new List<PriceBookEntry>();
        for(Product2 p: prods)
        {
            PriceBookEntry pbe=new PriceBookEntry();
            pbe.isActive=true;
            pbe.Pricebook2Id=Constants.STANDARD_PRICEBOOK_ID;
            pbe.Product2Id=p.Id;
            pbe.UnitPrice=10;
            listPBE.add(pbe);
        }
        return listPBE;
    }
  
    /**
* @name CreateAccounts
* @description Constructs a list of Account records for unit tests
**/
    public static List<Account> ConstructAccounts(Integer cnt){
        //ToDo: Ensure this method returns a list of size cnt of uniquely named Account records
        //  with all of the required fields populated.
        List<Account> listAcc=new List<Account>();
        for(Integer n=0;n<cnt;n++)
        {
            Account a=new Account();
            a.Name='TEST1_'+n;
            listAcc.add(a);
        }
      
        return listAcc;
    }
  
    /**
* @name CreateContacts
* @description Constructs a list of Contacxt records for unit tests
**/
    public static List<Contact> ConstructContacts(Integer cnt, List<Account> accts){
        //ToDo: Ensure this method returns a list, of size cnt, of uniquely named Contact records
        //  related to the provided Accounts
        //  with all of the required fields populated.
        List<Contact> listCC=new List<Contact>();
      
        for(Integer n=0;n<cnt;n++)
        {
            Contact c=new Contact();
            c.LastName='LN1_'+n;
            c.AccountId=accts[n].Id;
            listCC.add(c);
          
        }
      
        return listCC;
    }
  
    /**
* @name CreateOrders
* @description Constructs a list of Order records for unit tests
**/
    public static List<Order> ConstructOrders(Integer cnt, List<Account> accts){
        //ToDo: Ensure this method returns a list of size cnt of uniquely named Order records
        //  related to the provided Accounts
        //  with all of the required fields populated.
      
        List<Order> listOrd=new List<Order>();
      
      
        for(Integer n=0;n<cnt;n++)
        {
            Order o=new Order();
            o.EffectiveDate=System.today();
            o.AccountId=accts[n].Id;
            o.Status='Draft';
            o.Pricebook2Id=Constants.STANDARD_PRICEBOOK_ID;
            listOrd.add(o);
          
        }
      
        return listOrd;
      
      
    }
  
    /**
* @name CreateOrderItems
* @description Constructs a list of OrderItem records for unit tests
**/
    public static List<OrderItem> ConstructOrderItems(integer cnt, list<pricebookentry> pbes, list<order> ords){
        //ToDo: Ensure this method returns a list of size cnt of OrderItem records
        //  related to the provided Pricebook Entries
        //  and related to the provided Orders
        //  with all of the required fields populated.
        //  Hint: Use the DEFAULT_ROWS constant for Quantity as it will be used in the next challenge
      
        List<OrderItem> listOi=new List<OrderItem>();
      
        for(Integer n=0; n<cnt;n++)
        {
            OrderItem oi=new OrderItem();
            oi.OrderId=ords[n].Id;
            oi.PricebookEntryId=pbes[n].id;
            oi.UnitPrice=pbes[n].UnitPrice;
            oi.Quantity=Constants.DEFAULT_ROWS;
          
          
            listOi.add(oi);
        }
      
        return listOi;
    }
  
    public static void VerifyQuantityOrdered(Product2 originalProduct, Product2 updatedProduct, Integer qtyOrdered)
    {
      
        //System.assertNotEquals(updatedProduct.Quantity_Ordered__c, originalProduct.Quantity_Ordered__c +qtyOrdered);
        //updatedProduct.Quantity_Ordered__c=originalProduct.Quantity_Ordered__c + qtyOrdered;
        Integer sumQ=Integer.valueOf(originalProduct.Quantity_Ordered__c) + qtyOrdered;
        System.assertEquals(updatedProduct.Quantity_Ordered__c, sumQ);
      
      
    }
  
  
    /**
* @name SetupTestData
* @description Inserts accounts, contacts, Products, PricebookEntries, Orders, and OrderItems.
**/
    public static void InsertTestData(Integer cnt){
        //ToDo: Ensure this method calls each of the construct methods
        //  and inserts the results for use as test data.
        CollaborationGroup cg = ConstructCollaborationGroup();
        insert cg;
        List<Account> accountList = ConstructAccounts(cnt);
        insert accountList;
        List<Contact> contactList = ConstructContacts(cnt, accountList);
        insert contactList ;
        List<Product2> prodList = ConstructProducts(cnt);
        insert prodList ;
        List<PriceBookEntry> pbeEntry = ConstructPricebookEntries(prodList);
        insert pbeEntry ;
        List<Order> orderList = ConstructOrders(cnt, accountList);
        insert orderList ;
        List<OrderItem> itemList = ConstructOrderItems(cnt, pbeEntry , orderList);
        insert itemList ;
      
    }
  
}
Product2Tests:
@isTest (seeAllData=false)
private class Product2Tests {
  
    /**
* @name product2Extension_UnitTest
* @description UnitTest for product2Extension
**/
    @isTest
    static void Product2Extension_UnitTest(){
        Test.startTest();
        PageReference pageRef = Page.Product2New;
        Test.setCurrentPage(pageRef);
        Product2 prod = new Product2(name='Test',isActive=true);      
        ApexPages.StandardController stdcontroller = new ApexPages.StandardController(prod);      
        Product2Extension ext = new Product2Extension(stdcontroller);      
        System.assertEquals(Constants.DEFAULT_ROWS, ext.productsToInsert.size());
        ext.addRows();
        System.assertEquals(Constants.DEFAULT_ROWS * 2, ext.productsToInsert.size());
        for (Integer i = 0; i < 5; i++) {
            Product2Extension.ProductWrapper wrapper = ext.productsToInsert[i];
            Product2 testProduct = new Product2();
            testProduct.Name = 'Test Product ' + i;
            testProduct.IsActive = true;
            testProduct.Initial_Inventory__c = 20;
            testProduct.Family = Constants.PRODUCT_FAMILY[0].getValue();
            wrapper.productRecord = testProduct;
            PricebookEntry testEntry = new PricebookEntry();
            testEntry.IsActive = true;
            testEntry.UnitPrice = 10;
            wrapper.pricebookEntryRecord = testEntry;
        }
        ext.save();
        ext.GetFamilyOptions();
        ext.GetInventory();
        Test.stopTest();
        List<Product2> createdProducts = [
            SELECT
            Id
            FROM
            Product2
        ];
        System.assertEquals(5, createdProducts.size());
    }
    static TestMethod void Product2Trigger_UnitTest(){
        Test.startTest();
        Product2 p=new Product2();
        p.Name='TestProduct';
        p.Family='Side';
        p.IsActive=true;
        p.Quantity_Ordered__c =50;
        p.Initial_Inventory__c =100;
        insert p;
        CollaborationGroup c=new CollaborationGroup();
        c.Name='Test Inventory Announcements';
        c.Description='test';
        c.CollaborationType='public';
        insert c;
        p.Quantity_Ordered__c=96;
        update p;
        Test.stopTest();
    }
    public static testMethod void test3()
    {
     Pricebook2 pb = new Pricebook2(Name = 'Standard Price Book 2009', Description = 'Price Book 2009 Products', IsActive = true);
     insert pb;
     Product2 prod = new Product2(Name ='Anti-infectives 2007', Family = 'Best Practices', IsActive = true);
     insert prod;
     PricebookEntry pbe = new PricebookEntry(Pricebook2Id = pb.Id, Product2Id = prod.Id, UnitPrice = 10000, IsActive = true, UseStandardPrice = false);
     insert pbe;
     Opportunity opp = new Opportunity(Name = 'Test Syndicated 2010', Type = 'Syndicated - New', StageName = 'Planning', CloseDate = system.today());
     insert opp;
     OpportunityLineItem oli = new OpportunityLineItem(opportunityId = opp.Id, pricebookentryId = pbe.Id, Quantity = 1, UnitPrice = 7500, Description = '2007 CMR #4 - Anti-Infectives');
     insert oli;
  List<OpportunityLineItem> olis = [Select Id From OpportunityLineItem Where OpportunityId =: opp.Id];
  update olis[0];
    }
}
OrderTests:
@isTest(SeeAllData=false)
public class OrderTests {
 
public  static Map<String, List<Object>> testData;
  
@isTest(SeeAllData=true) static void OrderUpdate_UnitTest (){
        TestDataFactory.InsertTestData(5);
        Order rec = [select id, Status from Order limit 1];
        Product2 prod = [SELECT Initial_Inventory__c,Family,Id,Name,Quantity_Ordered__c,Quantity_Remaining__c FROM Product2 where name ='Side' limit 1];
        system.debug('product2Controller => '+prod.Quantity_Ordered__c);
        system.debug('Quantity_Remaining__c => '+prod.Quantity_Remaining__c);
        rec.status = constants.ACTIVATED_ORDER_STATUS;
        Update rec;
        Product2 updatedprod = [SELECT Initial_Inventory__c,Family,Id,Name,Quantity_Ordered__c,Quantity_Remaining__c FROM Product2 Where name ='Side' limit 1];
        system.debug('itial_Inventory__c =>'+updatedprod.Initial_Inventory__c);
        system.debug('Quantity_Ordered__c =>'+updatedprod.Quantity_Ordered__c);
        system.debug('Quantity_Remaining__c =>'+updatedprod.Quantity_Remaining__c);
        TestDataFactory.VerifyQuantityOrdered(prod,updatedprod,constants.DEFAULT_ROWS);
      
        //upsert updatedprod;
    }  
@isTest(SeeAllData=true) static void OrderExtension_UnitTest(){
        Order rec = [select id, Status from Order limit 1];
        PageReference pageRef = Page.OrderEdit;
        Test.setCurrentPage(pageRef);
        pageRef.getParameters().put('id',rec.id);
        ApexPages.StandardController sc = new ApexPages.standardController(rec);
      
        OrderExtension cc = new OrderExtension(sc);
        cc.SelectFamily();
        cc.OnFieldChange();
        cc.Save();
        cc.First();
        cc.Next();
        cc.Previous();
        cc.Last();
        cc.GetHasPrevious();
        cc.GetHasNext();
        cc.GetTotalPages();
        cc.GetFamilyOptions();
      
        ChartHelper.GetInventory();
        //Constants.getStdPriceBook();
}
//@testSetup static void SetupTestData (){
  
//}
}