I have done following function to the help of apex class and trigger. the concept is like the sync mode in the quote to that related opportunity if we created any product in the quote line item that automatically updated to the Opportunity Line Item (i.e product of that opportunity).

here there are two custom fields in the same named "SyncCheck__c" to the Opportunity Line Item(Opportunity Product) and quote Line Item as per object respectively. the custom field is a text area field so if I written to the quote line item in the field Like 'check' if the quote is sync to the opportunity then the word 'check' is updated to the field in the opportunity product of the same product in the same named field.

So I write test class followingly, My test class:

public class TestCustomSyncHandlerTrigger {
    static testMethod void  UpdateCustomSyncHandler() {
        QuoteLineItem QLI  = new QuoteLineItem();
        OpportunityLineItem OLI = new OpportunityLineItem();
        insert QLI;
        insert OLI;
        if (QLI.Quote.isSyncing == True ) {
            QLI.SyncCheck__c = 'check';
           OLI.SyncCheck__c = QLI.SyncCheck__c; 
        system.assertEquals (OLI.SyncCheck__c, 'check' );



but it's not covered any portion it's provide the error only so please help me to done this testclass .

My Trigger:

trigger customSyncHandlerTrigger on QuoteLineItem (after update) {
     if (Trigger.isUpdate && Trigger.isAfter) {   
         CustomSyncHandler.UpdateTrigger(Trigger.New, Trigger.OldMap);
    } }

Apex class:

public class CustomSyncHandler {

    public static void UpdateTrigger (List<QuoteLineItem> InsertedQuote, Map<Id,QuoteLineItem> OldInsertedQuoteMap) {

        Set<Id> ProductIdset = new Set<Id>();
        Set<Id> QuoteIdset = new Set<Id>();
        Set<Id> OpportunityIdset = new Set<Id>();
        List<QuoteLineItem> QuoteLineItemList = new List<QuoteLineItem>();
        List<OpportunityLineItem> OpportunityLineItemList = new List<OpportunityLineItem>();

        for (QuoteLineItem RecordQuoteItem: InsertedQuote) {

           QuoteLineItem OldQuoteLineItemREC = OldInsertedQuoteMap.get(RecordQuoteItem.Id);

           if (OldQuoteLineItemREC.SyncCheck__c != RecordQuoteItem.SyncCheck__c) {



        If (QuoteIdset.size()>0) {

            QuoteLineItemList = [SELECT Id, QuoteId, Product2Id, SyncCheck__c, Quote.issyncing, Quote.OpportunityId FROM QuoteLineItem WHERE Product2Id IN :ProductIdset AND Quote.issyncing = True  ];

        If (QuoteLineItemList.size() > 0) {

            for (QuoteLineItem quoteLineitemvalue: QuoteLineItemList) {                  

        List<OpportunityLineItem> OpportunityLineitemvalueList = [SELECT Id, Name, OpportunityId, SyncCheck__c, Product2Id FROM OpportunityLineItem WHERE OpportunityId IN :OpportunityIdset AND Product2Id IN :ProductIdset];

        Map<Id, List<OpportunityLineItem>> OpportunityandOppolineitemMap = new Map<Id, List<OpportunityLineItem>>();

        for (OpportunityLineItem OpportunityLIRecord : OpportunityLineitemvalueList) {

            If (!OpportunityandOppolineitemMap.Containskey(OpportunityLIRecord.Id)) {

                OpportunityandOppolineitemMap.put(OpportunityLIRecord.OpportunityId, new List<OpportunityLineItem>());                



        system.debug('@@@ OpportunityandOppolineitemMap value is'+OpportunityandOppolineitemMap);

        for (QuoteLineItem QuoteLineItemRecord : QuoteLineItemList) { 

            if (OpportunityandOppolineitemMap.containsKey(QuoteLineItemRecord.Quote.OpportunityId)) {  

                 for (OpportunityLineItem OpporVar : OpportunityandOppolineitemMap.get(QuoteLineItemRecord.Quote.OpportunityId)) {

                     if (OpporVar.Product2Id == QuoteLineItemRecord.Product2Id) {

                         OpporVar.SyncCheck__c = QuoteLineItemRecord.SyncCheck__c;

        if (OpportunityLineItemList.size() > 0) {

            Update OpportunityLineItemList;  


For any answer to this question is appreciated and thanks in advance.

  • 1
    In a very high level view, your trigger is for after UPDATE but you are never updating the record in test class, you are only inserting. Update the record to cover the test class. Nov 14, 2016 at 11:52
  • @SantanuHalder thanks for the reply it's provide the error for the insert failed for that QLI in line 5 also that's why I want help. Really I don't know to how to write a test class in case I provide the command of Update to that in which manner? can you make some changes in my code please it's help for to known about that...
    – Raj
    Nov 14, 2016 at 12:03

2 Answers 2


Here is something to get you started (make sure you scroll in the code as the actual tests are below the scroll line). Basic debugging will be required

public class TestCustomSyncHandlerTrigger {

    @TestSetup private static void setUpData(){

        Account a = New Account(Name='Test');
        insert a;

        Opportunity o = New Opportunity(
                StageName = 'test',
                CloseDate = date.today(), 
                Name = 'test', 
                AccountId = a.id

        insert o;

        //....Create Products, pricebookentries, etc needed for the QLI and the OLI

        OpportunityLineItem oli = New OpportunityLineItem(

        insert oli;

        Quote q = New Quote(


        insert q;

        QuoteLineItem qli = New QuoteLineItem(

        insert qli;


    static testMethod void  basicTest() {

        QuoteLineitem qli = [Select Id, ... From QuoteLineItem]; //We know we created one and only one

        qli.SyncCheck__c = 'check'; //This is what your code looks to compare if it should run;

        update qli; //This should fire your code

        //Query for OLI and assert the field was updated appropriatly
        OpportunityLineItem oli = [Select SyncCheck__c From OpportunityLineItem];

        system.assertEquals('check',oli.SyncCheck__c, 'The field was not updated when it should have been');


    static testMethod void  basicTest_NoProductMatch() {
        //Negative Use case
        //Create a QLI that does not have a corresponding OLI with same product
        QuoteLineitem qli = New QuoteLineItem(.....);
        insert qli;

        qli.SyncCheck__c = 'check'; //This is what your code looks to compare if it should run;

        update qli; //This should fire your code

        //Query for OLI and assert the field was NOT updated since Product match was not found (quoery requirement in your code)
        OpportunityLineItem oli = [Select SyncCheck__c From OpportunityLineItem];

        system.assertNotEquals('check',oli.SyncCheck__c,'The field was updated when the product did not match the updated QLI');




  1. TestSetup to create your base data that every test method should use
  2. Think through what you code and business requirements need when manipulating your test data to make the magic happen
  3. Write several test cases covering both positive and negative use cases.

You could add several more variations of the tests to cover outlier scenarios or anything else you may think would come up.

Then and only then review code coverage. If it is not > 90%, review the coverage and decide if the uncovered code is needed (Why was it not covered when your tests cover all use cases). If not needed remove it. If needed, write a test method to cover that scenario.


I can not write the whole test class for you for obvious reasons.

I can give you guidelines on how to do that. First you have to create the parents of the records, in this case Quote & Opportunity. Once created, use their ID as parent for QLI & OLI respectively and then insert QLI & OLI. Next, update the desired field of the QLI and update the record, it will call the after update trigger.

Hope it will help.

For more on how to write test class, please visit this link.


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .