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
travis.truetttravis.truett 

Test Class fails at system.assertequals

I wrote a trigger that duplicates Opportunities when their stage is updated to "Closed Won." The trigger also copies over some associated objects from the duplicated opp, changes the name of the new opp, and populates a field in the "Child Opportunity" called Parent_Opportunity__c, which contains the Id of the parent. The following code is my test, which I can't get to work right. It fails at the assertion statement. I'm trying to create an opportunity, add a product to it, and then change the stage to Closed Won, which should run the trigger, and then test that there exists a new opportunity with the original opportunity's Id as its Parent Opportunity.

Thanks in advance for the help. Here's the code:

@isTest (seeAllData=true)
private class testCreateFollowup{

static testMethod void test_Create_Followup() {

List<Account> aList = new List<Account>();    
Account a = new Account(
      Name = 'Test Account'
    );
    aList.add(a);
    
    insert aList;
    

List<Opportunity> oList = new List<Opportunity>();
Opportunity o = new Opportunity(
      Name = 'Test Opportunity', 
      StageName = 'Discovery', 
      CloseDate = Date.today(), 
      AccountId = a.Id
    );
    
    oList.add(o);
    insert oList;


        //Create Product
        Product2 prod = new Product2();
        prod.IsActive = true;
        prod.Name = 'Onboarding';
        prod.CanUseRevenueSchedule=true;
        insert prod;
        //Create PriceBook
        Pricebook2 pb = new Pricebook2();
        pb.Name = 'Test';
        pb.IsActive = true;
        insert pb;
    Pricebook2 standardpb = [Select Id, Name, IsActive From Pricebook2 where IsStandard = true LIMIT 1];
        
            
        PricebookEntry standardpbe = new PricebookEntry();
        standardpbe.Pricebook2Id = standardpb.Id;
        standardpbe.Product2Id = prod.Id;
        standardpbe.UnitPrice = 10000;
        standardpbe.IsActive = true;
        standardpbe.UseStandardPrice = false;
        insert standardpbe;
        
        PricebookEntry pbe = new PricebookEntry();
        pbe.Pricebook2Id = pb.Id;
        pbe.Product2Id = prod.Id;
        pbe.UnitPrice = 10000;
        pbe.IsActive = true;
        pbe.UseStandardPrice = false;
        insert pbe;
        

List<OpportunityLineItem> oliAnnuallyList = new List<OpportunityLineItem>(); 
       
OpportunityLineItem oliAnnually = new OpportunityLineItem(
        OpportunityId = o.Id,  
        PricebookEntryId = pbe.id,
        TotalPrice = 1,
        Quantity=2,
        Payment_Terms__c ='Annually',
        Duration__c = 12
        
    );
    
    oliAnnuallyList.add(oliAnnually);
    
    insert oliAnnuallyList;
    
    o.Stagename = 'Closed Won';

 List<Opportunity> lstOpty =[SELECT Parent_Opportunity__c from Opportunity];
 System.assertequals(lstOpty[0].Parent_Opportunity__c, o.Id);

}
}
Himanshu ParasharHimanshu Parashar
Hi Travis,

You need to update the Opportunity after 

o.Stagename = 'Closed Won';

so your code will be 
 
o.Stagename = 'Closed Won';
update o;

Thanks,
Himanshu
travis.truetttravis.truett
I'm getting a system.dml exception at the update line. Not sure why.
Himanshu ParasharHimanshu Parashar
Can you post the error.
travis.truetttravis.truett
Here's the error:

System.DmlException: Update failed. First exception on row 0 with id 006K000000D3GowIAF; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, Create_followup: execution of BeforeUpdate caused by: System.DmlException: Insert failed. First exception on row 0; first error: FIELD_INTEGRITY_EXCEPTION, field integrity exception: PricebookEntryId (pricebook entry is in a different pricebook than the one assigned to the opportunity): [PricebookEntryId] Trigger.Create_followup: line 68, column 1: []

Here's the trigger:

trigger Create_followup on Opportunity (before update, after insert) {
    Pricebook2 standardBook = [SELECT Id FROM Pricebook2 WHERE Name = :'Ambition'];//Create an instance of the standard pricebook
    
    if(Trigger.isUpdate){
        List<Opportunity> listOppor = new List<Opportunity>();
        for (Opportunity o: Trigger.new){
            if (o.StageName == 'Closed Won' && o.Stage_Change__c == false){

                Opportunity oppNew = o.clone();
                oppNew.Name = oppNew.Name  + ' - Annual ' + o.CloseDate.year();
                
                if(o.Renewal_Date__c != null){
                oppNew.Renewal_Date__c = o.Renewal_Date__c.addYears(1);
                oppNew.CloseDate = o.Renewal_Date__c.addYears(1);}
                
                oppNew.StageName = 'Discovery';
                oppNew.Probability = 25;
                oppNew.Parent_Opportunity__c = o.Id;
                
                
                oppNew.Pricebook2Id = standardBook.Id;//associate the standard pricebook with this opportunity
                
                oppNew.Is_Clone__c = true;
                listOppor.add(oppNew);
                o.Stage_Change__c = true;
                
            }

        }//end of for loop

        if(listOppor.size() > 0){
            insert listOppor;
            
            List<OpportunityContactRole> ocrList = [SELECT OpportunityId, ContactId, Role FROM OpportunityContactRole WHERE OpportunityId IN :Trigger.New];
            List<OpportunityContactRole> newOcrList = new List<OpportunityContactRole>();

            if(!ocrList.isEmpty()) {
                Map<Id, Id> oldOpNewOpIdMap = new Map<Id, Id>();
                for(Opportunity opNew : listOppor) {
                    oldOpNewOpIdMap.put(opNew.Parent_Opportunity__c, opNew.Id);
                }   
                for(OpportunityContactRole ocr : ocrList) {
                    OpportunityContactRole newOcr = new OpportunityContactRole();
                    newOcr.ContactId = ocr.ContactId;
                    newOcr.Role = ocr.Role;
                    newOcr.OpportunityId = oldOpNewOpIdMap.get(ocr.OpportunityId);
                    newOcrList.add(newOcr);
                }
                insert newOcrList;
            }
            
          List<OpportunityLineItem> oliList = [SELECT OpportunityId, PricebookEntryId, TotalPrice, Quantity FROM OpportunityLineItem WHERE OpportunityId IN :Trigger.New];
          List<OpportunityLineItem> newoliList = new List<OpportunityLineItem>();
          
          if(!oliList.isEmpty()) {
                Map<Id, Id> oldOpNewOpIdMap2 = new Map<Id, Id>();
                for(Opportunity opNew : listOppor) {
                    oldOpNewOpIdMap2.put(opNew.Parent_Opportunity__c, opNew.Id);
                }   
                for(OpportunityLineItem oli : oliList) {
                    OpportunityLineItem newOli = new OpportunityLineItem();
                    newOli.TotalPrice = oli.TotalPrice;
                    newOli.PricebookEntryId = oli.PricebookEntryId;
                    newOli.Quantity = oli.Quantity;
                    newOli.OpportunityId = oldOpNewOpIdMap2.get(oli.OpportunityId);
                    newoliList.add(newOli);
                }
                insert newoliList;
            }

            
        }
        
        

    }

    if(trigger.isInsert){
        try{
            //OpportunityLineItem[] lines = new OpportunityLineItem[0];
            //PricebookEntry entry = [SELECT Id, UnitPrice FROM PricebookEntry WHERE Pricebook2Id = :standardBook.Id AND Product2.ProductCode = 'ENTERPRISE_ANNUAL_UPFRONT'];
            List<Event> eventList = new List<Event>();
            //List<Note> noteList = new List<Note>();


            for(Opportunity o: Trigger.new){
                if(o.Is_Clone__c == true){

                    //noteList.add(new Note(ParentId=o.id,Title='Matt is the Apex_God',Body='Matt is the Apex_God',isPrivate=false));

                    //lines.add(new OpportunityLineItem(PricebookEntryId=entry.Id, OpportunityId=o.Id, UnitPrice=entry.UnitPrice, Quantity=1));

                    if(o.Renewal_Date__c != null){

                        DateTime myDateTime = o.Renewal_Date__c.addMonths(-10);
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime,subject='Account Management Follow-Up', EndDateTime=myDateTime, IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(2),subject='Account Management Follow-Up', EndDateTime=myDateTime.addMonths(2), IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(4),subject='Account Management Follow-Up', EndDateTime=myDateTime.addMonths(4), IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(6),subject='Account Management Follow-Up', EndDateTime=myDateTime.addMonths(6), IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(8),subject='Account Management Follow-Up', EndDateTime=myDateTime.addMonths(8), IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(10),subject='Account Management Follow-Up', EndDateTime=myDateTime.addMonths(10), IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(10),subject='Renewal',EndDateTime=myDateTime.addMonths(10), IsAllDayEvent=true));
                        eventList.add(new Event(whatid=o.id,startdatetime=myDateTime.addMonths(9),subject='Sales Contract Follow-Up',EndDateTime=myDateTime.addMonths(9), IsAllDayEvent=true));

                    }//end of if

                }
            }
            //insert lines;
            insert eventList;
            //insert noteList;

        }
        catch(Exception e){

        }
    }
}
Himanshu ParasharHimanshu Parashar
Try with following test class code
 
@isTest (seeAllData=true)
private class testCreateFollowup{

static testMethod void test_Create_Followup() {

List<Account> aList = new List<Account>();    
Account a = new Account(
      Name = 'Test Account'
    );
    aList.add(a);
    
    insert aList;
    

List<Opportunity> oList = new List<Opportunity>();
Opportunity o = new Opportunity(
      Name = 'Test Opportunity', 
      StageName = 'Discovery', 
      CloseDate = Date.today(), 
      AccountId = a.Id
    );
    
    oList.add(o);
    insert oList;


        //Create Product
        Product2 prod = new Product2();
        prod.IsActive = true;
        prod.Name = 'Onboarding';
        prod.CanUseRevenueSchedule=true;
        insert prod;
        //Create PriceBook
        Pricebook2 pb = new Pricebook2();
        pb.Name = 'Test';
        pb.IsActive = true;
        insert pb;
    Pricebook2 standardpb = [Select Id, Name, IsActive From Pricebook2 where IsStandard = true LIMIT 1];
        
            
        PricebookEntry standardpbe = new PricebookEntry();
        standardpbe.Pricebook2Id = standardpb.Id;
        standardpbe.Product2Id = prod.Id;
        standardpbe.UnitPrice = 10000;
        standardpbe.IsActive = true;
        standardpbe.UseStandardPrice = false;
        insert standardpbe;
        
        PricebookEntry pbe = new PricebookEntry();
        pbe.Pricebook2Id = pb.Id;
        pbe.Product2Id = prod.Id;
        pbe.UnitPrice = 10000;
        pbe.IsActive = true;
        pbe.UseStandardPrice = false;
        insert pbe;
        

List<OpportunityLineItem> oliAnnuallyList = new List<OpportunityLineItem>(); 
       
OpportunityLineItem oliAnnually = new OpportunityLineItem(
        OpportunityId = o.Id,  
        PricebookEntryId = standardpb.id,
        TotalPrice = 1,
        Quantity=2,
        Payment_Terms__c ='Annually',
        Duration__c = 12
        
    );
    
    oliAnnuallyList.add(oliAnnually);
    
    insert oliAnnuallyList;
    
    o.Stagename = 'Closed Won';

 List<Opportunity> lstOpty =[SELECT Parent_Opportunity__c from Opportunity];
 System.assertequals(lstOpty[0].Parent_Opportunity__c, o.Id);

}
}

 
travis.truetttravis.truett
System.DmlException: Insert failed. First exception on row 0; first error: FIELD_INTEGRITY_EXCEPTION, Price Book Entry ID: id value of incorrect type: 01sU000000018yjIAA: [PricebookEntryId]
Class.testCreateFollowup.test_Create_Followup: line 72, column 1

I noticed the update line was gone. does that need to be added back in?
Himanshu ParasharHimanshu Parashar
@isTest (seeAllData=true)
private class testCreateFollowup{

static testMethod void test_Create_Followup() {

List<Account> aList = new List<Account>();    
Account a = new Account(
      Name = 'Test Account'
    );
    aList.add(a);
    
    insert aList;
    

List<Opportunity> oList = new List<Opportunity>();
Opportunity o = new Opportunity(
      Name = 'Test Opportunity', 
      StageName = 'Discovery', 
      CloseDate = Date.today(), 
      AccountId = a.Id
    );
    
    oList.add(o);
    insert oList;


        //Create Product
        Product2 prod = new Product2();
        prod.IsActive = true;
        prod.Name = 'Onboarding';
        prod.CanUseRevenueSchedule=true;
        insert prod;
        //Create PriceBook
        Pricebook2 pb = new Pricebook2();
        pb.Name = 'Test';
        pb.IsActive = true;
        insert pb;
    Pricebook2 standardpb = [Select Id, Name, IsActive From Pricebook2 where IsStandard = true LIMIT 1];
        
            
        PricebookEntry standardpbe = new PricebookEntry();
        standardpbe.Pricebook2Id = standardpb.Id;
        standardpbe.Product2Id = prod.Id;
        standardpbe.UnitPrice = 10000;
        standardpbe.IsActive = true;
        standardpbe.UseStandardPrice = false;
        insert standardpbe;
        
        PricebookEntry pbe = new PricebookEntry();
        pbe.Pricebook2Id = pb.Id;
        pbe.Product2Id = prod.Id;
        pbe.UnitPrice = 10000;
        pbe.IsActive = true;
        pbe.UseStandardPrice = false;
        insert pbe;
        

List<OpportunityLineItem> oliAnnuallyList = new List<OpportunityLineItem>(); 
       
OpportunityLineItem oliAnnually = new OpportunityLineItem(
        OpportunityId = o.Id,  
        PricebookEntryId = [select Id, CurrencyIsoCode from PricebookEntry where isactive=true limit 1][0],
        TotalPrice = 1,
        Quantity=2,
        Payment_Terms__c ='Annually',
        Duration__c = 12
        
    );
    
    oliAnnuallyList.add(oliAnnually);
    
    insert oliAnnuallyList;
    
    o.Stagename = 'Closed Won';

 List<Opportunity> lstOpty =[SELECT Parent_Opportunity__c from Opportunity];
 System.assertequals(lstOpty[0].Parent_Opportunity__c, o.Id);

}
}
travis.truetttravis.truett
It doesn't recognize CurrencyIsoCode

Error: Compile Error: No such column 'CurrencyIsoCode' on entity 'PricebookEntry'. If you are attempting to use a custom field, be sure to append the '__c' after the custom field name. Please reference your WSDL or the describe call for the appropriate names. at line 62 column 28
Himanshu ParasharHimanshu Parashar
Hi Travis,

Multicurrency is not enabled for your org so you can remove CurrencyIsoCode from SOQL at line 62
travis.truetttravis.truett
I'm still getting a compile error. It doesn't like that select statement for some reason...

Error: Compile Error: Invalid initial expression type for field OpportunityLineItem.PricebookEntryId, expecting: Id at line 62 column 88
 
Himanshu ParasharHimanshu Parashar
aah ok, try following code
 
@isTest (seeAllData=true)
private class testCreateFollowup{

static testMethod void test_Create_Followup() {

List<Account> aList = new List<Account>();    
Account a = new Account(
      Name = 'Test Account'
    );
    aList.add(a);
    
    insert aList;
    

List<Opportunity> oList = new List<Opportunity>();
Opportunity o = new Opportunity(
      Name = 'Test Opportunity', 
      StageName = 'Discovery', 
      CloseDate = Date.today(), 
      AccountId = a.Id
    );
    
    oList.add(o);
    insert oList;


        //Create Product
        Product2 prod = new Product2();
        prod.IsActive = true;
        prod.Name = 'Onboarding';
        prod.CanUseRevenueSchedule=true;
        insert prod;
        //Create PriceBook
        Pricebook2 pb = new Pricebook2();
        pb.Name = 'Test';
        pb.IsActive = true;
        insert pb;
    Pricebook2 standardpb = [Select Id, Name, IsActive From Pricebook2 where IsStandard = true LIMIT 1];
        
            
        PricebookEntry standardpbe = new PricebookEntry();
        standardpbe.Pricebook2Id = standardpb.Id;
        standardpbe.Product2Id = prod.Id;
        standardpbe.UnitPrice = 10000;
        standardpbe.IsActive = true;
        standardpbe.UseStandardPrice = false;
        insert standardpbe;
        
        PricebookEntry pbe = new PricebookEntry();
        pbe.Pricebook2Id = pb.Id;
        pbe.Product2Id = prod.Id;
        pbe.UnitPrice = 10000;
        pbe.IsActive = true;
        pbe.UseStandardPrice = false;
        insert pbe;
        

List<OpportunityLineItem> oliAnnuallyList = new List<OpportunityLineItem>(); 
       
OpportunityLineItem oliAnnually = new OpportunityLineItem(
        OpportunityId = o.Id,  
        TotalPrice = 1,
        Quantity=2,
        Payment_Terms__c ='Annually',
        Duration__c = 12
        
    );

oliAnnually.PricebookEntryId = [select Id from PricebookEntry where isactive=true limit 1][0];

    
    oliAnnuallyList.add(oliAnnually);
    
    insert oliAnnuallyList;
    
    o.Stagename = 'Closed Won';

 List<Opportunity> lstOpty =[SELECT Parent_Opportunity__c from Opportunity];
 System.assertequals(lstOpty[0].Parent_Opportunity__c, o.Id);

}
}

 
travis.truetttravis.truett
It really doesn't like that select statement haha

Error: Compile Error: Illegal assignment from PricebookEntry to Id at line 69 column 1
Himanshu ParasharHimanshu Parashar
I am sure following will work. :P
 
oliAnnually.PricebookEntryId = [select Id from PricebookEntry where isactive=true limit 1][0].id;

 
travis.truetttravis.truett
It's gone back to failing at the assertion. Looks like the ids don't match up

System.AssertException: Assertion Failed: Expected: 006K000000D2k7vIAB, Actual: 006K000000D3LmNIAV
Class.testCreateFollowup.test_Create_Followup: line 79, column 1
Himanshu ParasharHimanshu Parashar
Hi Travis,

Have you added "update o;" after

o.Stagename = 'Closed Won';

Sorry I missed that in my code.
 
travis.truetttravis.truett
Right. I forgot to add that. Now it fails at the update. This thing really doesn't want to run. Looks like some sort of error with the opp product...

System.DmlException: Update failed. First exception on row 0 with id 006K000000D3QT5IAN; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, Create_followup: execution of BeforeUpdate caused by: System.DmlException: Insert failed. First exception on row 0; first error: FIELD_INTEGRITY_EXCEPTION, field integrity exception: PricebookEntryId (pricebook entry is in a different pricebook than the one assigned to the opportunity): [PricebookEntryId] Trigger.Create_followup: line 68, column 1: []
Class.testCreateFollowup.test_Create_Followup: line 77, column 1

 
Himanshu ParasharHimanshu Parashar
Hi Travis,

We will crack this out don't worry ;)

Replace line 69 with
 
oliAnnually.PricebookEntryId = [select Id,Pricebook2.name from PricebookEntry where Pricebook2.name='Ambition' limit 1][0].id;
travis.truetttravis.truett
Grabbing the wrong Id again I think

System.AssertException: Assertion Failed: Expected: 006K000000D2k7vIAB, Actual: 006K000000D3QUhIAN
Class.testCreateFollowup.test_Create_Followup: line 81, column 1
travis.truetttravis.truett
I also noticed that the size of lstOpty is 4, even though we only duplicated one opportunity. That might have to do with the problem in some way
Himanshu ParasharHimanshu Parashar
try to print all lst opportunity id and check which one is the correct one. 
travis.truetttravis.truett
How do I actually print out like that? I haven't been able to figure that out yet
travis.truetttravis.truett
I added some debug statements to my test, but after I ran it and checked my debug logs, there were no new debug log entries
Himanshu ParasharHimanshu Parashar
have you added user ?
 
travis.truetttravis.truett
Ah. Yeah, I added that, and got the debug info. It looks like there are four elements in the list for some reason, but one of them is the correct Id. Here's a section of the debug. The first four debug calls are from lstOpty, and the last one is simply o.Id. So that first line, which I believe is from lstOpty[3], has a parent Id that matches o.Id. I'm not sure what the other elements in the list are, though, or how to fix it.



09:56:46.627 (19627562297)|USER_DEBUG|[84]|DEBUG|heyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyOpportunity:{Parent_Opportunity__c=006K000000D3aSmIAJ, Id=006K000000D3aSnIAJ}


09:56:46.627 (19627699951)|USER_DEBUG|[84]|DEBUG|heyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyOpportunity:{Id=006K000000D3aSmIAJ}


09:56:46.627 (19627826794)|USER_DEBUG|[84]|DEBUG|heyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyOpportunity:{Id=006K000000D2k7vIAB}


09:56:46.627 (19627987371)|USER_DEBUG|[84]|DEBUG|heyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyOpportunity:{Parent_Opportunity__c=006K000000D2k7vIAB, Id=006K000000D2lWKIAZ}


09:56:46.628 (19628120203)|USER_DEBUG|[86]|DEBUG|heyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy006K000000D3aSmIAJ

 
travis.truetttravis.truett
I changed the System.assert statement to System.assertequals(lstOpty[3].Parent_Opportunity__c, o.Id); and the test worked. It has brought my test up to 65% coverage....can you think of anything I can do to bump it up another 10%? Thanks so much for your help
Himanshu ParasharHimanshu Parashar
Hi Travis,

That is great. can you post screenshot from develoer console of your trigger so that I can see which line is not covered.
travis.truetttravis.truett
I actually added some code and brought it up to 82%. Here's the only part that isn't covered now.User-added image
travis.truetttravis.truett
I need an assertion statement testing that the contact roles were copied over.
Himanshu ParasharHimanshu Parashar
Hi Travis,

It is not covering that code and showing it in red lines because you are not creating contactroles in your test class.

follow below steps to cover those lines

1. Create a contact in test class
2. Create Opportunity contactrole in test class after creating opportunity after line 24