I have an after insert method on OpportunityLineItem that I'm writing a test class for. A problem that I had is I couldn't get the test to assert on the list passed to it because a formula was null when I expected it to be populated.
I thought to myself if I just reproduce the formula into the trigger logic then I can get around the issue but in doing so I've stopped the logic from working entirely where it worked in the UI before.
Consider this example:
I have a formula field "Product Family" that has the following syntax:
Text(PricebookEntry.Product2.Family)
When I put it into this method it works when you create a new OpportunityLineItem record in the UI, the solution consultant field is populated:
public static void populateSolutionsConsultant(List<OpportunityLineItem> newList)
{
List<OpportunityTeamMember> teamMembers = new List<OpportunityTeamMember>();
Map<Id,List<OpportunityLineItem>> oppToLineItem = new Map<Id,List<OpportunityLineItem>>();
for(OpportunityLineItem oli:newList)
{
if(oli.Product_Family__c == 'Analytic Solutions')
{
if(oppToLineItem.get(oli.OpportunityId)==null)
{
List<OpportunityLineItem> oliLst = new List<OpportunityLineItem>();
oliLst.add(oli);
oppToLineItem.put(oli.OpportunityId,oliLst);
}
else
{
oppToLineItem.get(oli.OpportunityId).add(oli);
}
}
}
teamMembers = [SELECT UserID,OpportunityId FROM OpportunityTeamMember where OpportunityId in:oppToLineItem.keyset() AND TeamMemberRole='Solutions Consultant'];
for(OpportunityTeamMember oppTeamMemb:teamMembers)
{
List<OpportunityLineItem> olis = oppToLineItem.get(oppTeamMemb.OpportunityId);
for(OpportunityLineItem line:olis)
{
line.Solution_Consultant__c = oppTeamMemb.UserID;
}
}
}
However, because I can't run my test on the formula I edited line looking for Analytic Solutions to be what the formula is, cutting the formula field out of the logic. Like this the solution consultant is not populated when created in the UI:
public static void populateSolutionsConsultant(List<OpportunityLineItem> newList)
{
List<OpportunityTeamMember> teamMembers = new List<OpportunityTeamMember>();
Map<Id,List<OpportunityLineItem>> oppToLineItem = new Map<Id,List<OpportunityLineItem>>();
for(OpportunityLineItem oli:newList)
{
if(oli.PricebookEntry.Product2.Family == 'Analytic Solutions')
{
if(oppToLineItem.get(oli.OpportunityId)==null)
{
List<OpportunityLineItem> oliLst = new List<OpportunityLineItem>();
oliLst.add(oli);
oppToLineItem.put(oli.OpportunityId,oliLst);
}
else
{
oppToLineItem.get(oli.OpportunityId).add(oli);
}
}
}
teamMembers = [SELECT UserID,OpportunityId FROM OpportunityTeamMember where OpportunityId in:oppToLineItem.keyset() AND TeamMemberRole='Solutions Consultant'];
for(OpportunityTeamMember oppTeamMemb:teamMembers)
{
List<OpportunityLineItem> olis = oppToLineItem.get(oppTeamMemb.OpportunityId);
for(OpportunityLineItem line:olis)
{
line.Solution_Consultant__c = oppTeamMemb.UserID;
}
}
}
Why can't I use "PricebookEntry.Product2.Family" in the if statement?
EDIT:
For reference this is the test class that I wrote that doesn't asset.. yet.
@isTest static void testSolutionConsultant()
{
List<OpportunityLineItem> lst = new List<OpportunityLineItem>();
Opportunity o = [SELECT Id FROM Opportunity];
PricebookEntry pbEntry = [SELECT Id FROM PricebookEntry];
Product2 prod = [SELECT Id, Family FROM Product2];
User u = [SELECT Id FROM User WHERE UserName = '[email protected]'];
Id tempId = getDummyID();
OpportunityTeamMember oTeam = new OpportunityTeamMember();
oTeam.UserID = u.Id;
oTeam.OpportunityId = o.Id;
oTeam.TeamMemberRole = 'Solutions Consultant';
oTeam.OpportunityAccessLevel = 'Read';
insert oTeam;
lst.add(new OpportunityLineItem(
Id = tempId,
OpportunityId = o.Id,
PricebookEntryId = pbEntry.Id,
Solution_Consultant__c = null
));
Test.startTest();
SL_OpportunityLineItemTriggerHandler.populateSolutionsConsultant(lst);
Test.stopTest();
System.assertEquals(u.Id, lst[0].Solution_Consultant__c,
'Solution Consultant should be populated');
}
SeeAllData
? That makes it a lot harder to help you.