Check string value in salesforce test class - salesforce

Below is the code for my test class.
Opportunity opp = [select Deal_Type__c from opportunity where Id: = <some id>];
Case objCase = new Case();
objCase.standard_or_nonstandard__c = 'Yes';
if(objCase.standard_or_nonstandard__c = 'Yes'){ // this if is getting tested
opp.Deal_Type__c = 'Standard';
}
else{ // else part is getting skipped
opp.Deal_Type__c = 'Not Standard';
}
And only first if condition is getting tested and other is skipping which is why the code is not reaching 75% off code coverage.
the field standard_or_nonstandard__c is picklist having two values Yes & No.
And if the value if Yes, the deal type should be standard, and if No, the deal type is not standard.
Any suggestion on this?

Because you're setting the field objCase.standard_or_nonstandard__c to 'Yes' before the condition. This means that there is no way for the field to be equal to 'No' when the condition is evaluated. So the first 'if' block is always entered and the else condition never is. You'll need to remove that line ( objCase.standard_or_nonstandard__c = 'Yes';) before the If statement in order for test data to be able to enter the else block.

You need to make some changes in your code to cover 75% code coverage.
you should try this one:
Opportunity opp = [select Deal_Type__c from opportunity where Id: = <some id>];
Case objCase = new Case();
objCase.standard_or_nonstandard__c = 'Yes';
opp.Deal_Type__c = 'Not Standard';
if(objCase.standard_or_nonstandard__c == 'Yes'){ // this if is getting tested
opp.Deal_Type__c = 'Standard';
}
Thanks,
Ajay Dubedi

Related

Need to optimize the code for mapping codes to description

I have a Text field that has semicolon separated codes. These code has to be replaced with the description. I have separate map that have code and description. There is a trigger that replace the code with their description. the data will loaded using the dataloader in this field. I am afraid, it might not work for large amount of data since I had to use inner for loops. Is there any way I can achieve this without inner for loops?
public static void updateStatus(Map<Id,Account> oldMap,Map < Id, Account > newMap)
{
Map<String,String> DataMap = new Map<String,String>();
List<Data_Mapper__mdt> DataMapList = [select Salseforce_Value__c,External_Value__c from Data_Mapper__mdt where
active__c = true AND Field_API_Name__c= :CUSTOMFIELD_MASSTATUS AND
Object_API_Name__c= :OBJECT_ACCOUNT];
for(Data_Mapper__mdt dataMapRec: DataMapList){
DataMap.put(dataMapRec.External_Value__c,dataMapRec.Salseforce_Value__c);
}
for(Account objAcc : newMap.values())
{
if(objAcc.Status__c != ''){
String updatedDescription='';
List<String> delimitedList = objAcc.Status__c.split('; ');
for(String Code: delimitedList) {
updatedDescription = DataMap.get(Code);
}
objAcc.Status__c = updatedDescription;
}
It should be fine. You have a map-based access acting like a dictionary, you have a query outside of the loop. Write an unit test that populates close to 200 accounts (that's how the trigger will be called in every data loader iteration). There could be some concerns if you'd have thousands of values in that Status__c but there's not much that can be done to optimise it.
But I want to ask you 3 things.
The way you wrote it the updatedDescription will always contain the last decoded value. Are you sure you didn't want to write something like updatedDescription += DataMap.get(Code) + ';'; or maybe add them to a List<String> and then call String.join on it. It looks bit weird. If you truly want first or last element - I'd add break; or really just access the last element of the split (and then you're right, you're removing the inner loop). But written like that this looks... weird.
Have you thought about multiple runs. I mean if there's a workflow rule/flow/process builder - you might enter this code again. And because you're overwriting the field I think it'll completely screw you over.
Map<String, String> mapping = new Map<String, String>{
'one' => '1',
'two' => '2',
'three' => '3',
'2' => 'lol'
};
String text = 'one;two';
List<String> temp = new List<String>();
for(String key : text.split(';')){
temp.add(mapping.get(key));
}
text = String.join(temp, ';');
System.debug(text); // "1;2"
// Oh noo, a workflow caused my code to run again.
// Or user edited the account.
temp = new List<String>();
for(String key : text.split(';')){
temp.add(mapping.get(key));
}
text = String.join(temp, ';');
System.debug(text); // "lol", some data was lost
// And again
temp = new List<String>();
for(String key : text.split(';')){
temp.add(mapping.get(key));
}
text = String.join(temp, ';');
System.debug(text); // "", empty
Are you even sure you need this code. Salesforce is perfectly fine with having separate picklist labels (what's visible to the user) and api values (what's saved to database, referenced in Apex, validation rules...). Maybe you don't need this transformation at all. Maybe your company should look into Translation Workbench. Or even ditch this code completely and do some search-replace before invoking data loader, in some real ETL tool (or even MS Excel)

How to select for multiple conditions to return one object that matches those conditions

I am creating a test, and am trying to create a method that pulls a specific job posting ID when it matches the job posting title, the job type and the description, just in case that the case that there are more than one job posting with the same title.
I cannot get the select statement to pull the job posting ID out of the instance variable. Debugging shows that there is indeed the ID nested in the instance variable, but my conditions aren't being met because I am not doing it correctly.
#job_posting is the instance variable that contains the ID that I need, but I need my parameters in select to match so I can subsequently return the ID.
whenever I ONLY use posting title,such as:
target_postings = #job_postings.select{|posting|posting[:posting_title]}
it works and returns the ID I need, however I cannot do this:
def get_specific_posting_id_for_posting(posting_title, job_type, description)
expect(#job_postings.length > 0)
target_postings = #job_postings.select {|posting| posting[:posting_title] == posting_title; posting[:job_type] == job_type; posting[:description] == description}
expect(target_postings.length == 1)
target_posting = target_postings[0]
posting_id = target_posting[:posting_id]
posting_id
end
It looks like
target_postings = #job_postings.select {|posting| posting[:posting_title] == posting_title; posting[:job_type] == job_type; posting[:description] == description}
should probably be
target_postings = #job_postings.select do |posting|
posting[:posting_title] == posting_title
&& posting[:job_type] == job_type
&& posting[:description] == description
end
Your version has three separate checks, the first two of which do nothing, only the last statement in the block is actually being used to determine whether the item matches.
As an aside, since it looks like you only want the single first element that matches your conditions, you might want to consider using find instead of select. It works the same except it will stop iterating and return as soon as it finds the first matching item.

Salesforce passing values to Multipicklist based on another object

long time no see, quick question about multipicklist in Apex.
Here is the condition:
1. Two standard objects: Task and Account, task is linked to account.
2. The subject field in the task contains three values: A, B, C.
3. Also, there is a field (Multipicklist)in the account contains the same values A, B, C
Every time I will create a task under a certain account, If I input subject with A, I hope the field in the account can be updated with A;
Then if I create a task with subject B, the field in the account should be (A;B)
So, here is my code:
if(IsSC && t.Status == PickListValuesStandard.Task_Completed){
Account student = new Account(Id = t.WhatId);
student.LatestCompletedActivity__pc = t.Subject;
student.LatestCompletedActivityDate__pc = t.ActivityDate;
if(t.Subject.contains('Post OC Call')){
student.Center_TouchPoints__c += (';Post OC Call');
}
if(t.Subject.contains('Third Week Call')){
student.Center_TouchPoints__c += (';Third Week Call');
}
update student;
}
The bolded part I attached above should be working like I described, Unfortunately, it didn't.
Can anyone help me understand the scenario? How can I achieve this?
Thanks in advance,
I just realized what a big mistake I've made, here is the thought, if I wanna update the multipicklist in the account, first thing first, I need to check whether it's null or not. Here is the update:
if(IsSC && t.Status == PickListValuesStandard.Task_Completed){
//Account student = new Account(Id = t.WhatId);
Account student = [select Center_TouchPoints__c from Account where Id=:t.WhatId];
student.LatestCompletedActivity__pc = t.Subject;
student.LatestCompletedActivityDate__pc = t.ActivityDate;
if(student.Center_TouchPoints__c==null){
if(t.Subject.contains('Post OC Call')){
student.Center_TouchPoints__c = 'Post OC Call;';
}
if(t.Subject.contains('Third Week Call')){
student.Center_TouchPoints__c = 'Third Week Call;';
}
}else if(student.Center_TouchPoints__c.contains ('Post OC Call') && t.Subject.contains('Third Week Call')){
student.Center_TouchPoints__c += ';Third Week Call';
}
update student;
}
However, if anyone of you has any better idea, please shoot me!
One way that might make this a bit more flexible is to loop through all the available values in the picklist and see if the task's subject contains that picklist value and if it does add that to the selected picklist values. This is assuming the name or label of the picklist entries match the values entered into the subject of the task. This way you will be able to add different entries or change the picklist values without changing the code. Here is an example of getting and looping through all picklist values
here's how I think that would look...
if(IsSC && t.Status == PickListValuesStandard.Task_Completed){
Account student = [select Center_TouchPoints__c from Account where Id=:t.WhatId];
student.LatestCompletedActivity__pc = t.Subject;
student.LatestCompletedActivityDate__pc = t.ActivityDate;
Schema.DescribeFieldResult fieldDescribe = account.Center_TouchPoints__c.getDescribe();
//retrieves picklist values
List<Schema.PicklistEntry> picklistVals = fieldResult.getPicklistValues();
String picklistString = '';
for(Schema.PicklistEntry plv : picklistVals){ //Loop through picklist values
if(t.subject.contains(plv.getValue()) && !student.Center_TouchPoints__c.contains(plv.getValue())) {
//If if this picklist value is in the subject and it hasn't been selected already add it.
picklistString += (plv.getValue() + '; ');
}
}
if(student.Center_TouchPoints__c == null)
student.Center_TouchPoints__c = picklistString.substring(1);
else
student.Center_TouchPoints__c += (';' + picklistString);
update student;
}
Hope this helps!

Can't update Boolean value in Apex

I cannot update update this Boolean value in Apex. What is going wrong? The if statement, and the fact that the front end representation is a checkbox, proves that it is indeed a boolean value. I am new to Apex so I feel its a basic misunderstanding of how it works. Can anyone help me out?
Here is the code that I'm executing in an Anonymous Window.
Account acc = new Account(Name='Test Name');
if (acc.Do_Not_Contact__pc == false) {
System.debug('DNC is false');
} else {
System.debug('DNC is true');
}
insert acc;
acc.Do_Not_Contact__pc = true;
update acc;
It fails on the second to last line, displaying the following message:
System.DmlException: Update failed. First exception on row 0 with id 001W000000fFiVbIAK; first error: INVALID_FIELD_FOR_INSERT_UPDATE, Account: bad field names on insert/update call: Do_Not_Contact__pc: [Do_Not_Contact__pc]
What's particularly frustrating is that when I change the second to last line to
acc.Do_Not_Contact__pc = 'true';
I get an error stating that I cannot assign a String to a Boolean value
Remove the single quotes and I assume you typed the field name wrong. Try acc.Do_Not_Contact__c = true;

Apex - Retrieving Records from a type of Map<SObject, List<SObject>>

I am using a lead map where the first id represents an Account ID and the List resembles a list of leads linked to that account such as: Map<id, List<Id> > leadMap = new Map< id, List<id> >();
My question stands as following: Knowing a Lead's Id how do I get the related Account's Id from the map. My code looks something like this, The problems is on the commented out line.
for (Lead l : leads){
Lead newLead = new Lead(id=l.id);
if (l.Company != null) {
// newLead.Account__c = leadMap.keySet().get(l.id);
leads_to_update.add(newLead);
}
}
You could put all lead id and mapping company id in the trigger then get the company id
Map<string,string> LeadAccountMapping = new Map<string,string>();//key is Lead id ,Company id
for(Lead l:trigger.new)
{
LeadAccountMapping.put(l.id,l.Company);
}
//put the code you want to get the company id
string companyid= LeadAccountMapping.get(l.id);
Let me make sure I understand your problem.
Currently you have a map that uses the Account ID as the key to a value of a List of Lead IDs - So the map is -> List. Correct?
Your goal is to go from Lead ID to the Account ID.
If this is correct, then you are in a bad way, because your current structure requires a very slow, iterative search. The correct code would look like this (replace your commented line with this code):
for( ID actID : leadMap.keySet() ) {
for( ID leadID : leadMap.get( actId ) ) {
if( newLead.id == leadID ) {
newLead.Account__c = actId;
leads_to_update.add(newLead);
break;
}
}
}
I don't like this solution because it requires iterating over a Map and then over each of the lists in each of the values. It is slow.
If this isn't bulkified code, you could do a Select Query and get the Account__c value from the existing Lead by doing:
newLead.Account__c = [ SELECT Account__c FROM Lead WHERE Id = :l.id LIMIT 1];
However, this relies on your code not looping over this line and hitting a governor limit.
Or you could re-write your code soe that your Map is actually:
Map<ID, List<Leads>> leadMap = Map<ID, List<Leads>>();
Then in your query where you build the map you ensure that your Lead also includes the Account__c field.
Any of these options should work, it all depends on how this code snippet in being executed and where.
Good luck!

Resources