0

Beginner disclaimer Apologies if this seems stupid but I've been a bit stumped by this. I have looked through documentation but cannot find the answer I need to here I am.

I have a custom object called Commission. It is related to Contact via a master-detail relationship called Awarded To.

When declaring a new commission (in a test class in my case) do I need to define both the __r and __c of the new object?

// Test data setup
Account acct = new Account(Name='Test Account');
insert acct;
Contact cont = new Contact(LastName='Doe', Primary__c=false,AccountId=acct.Id);
insert cont;    

Test.startTest();
Commission__c comm = new Commission__c(Amount__c=2000);
comm.Awarded_To__r = cont;
comm.Awarded_To__c = cont.Id;
insert comm;
Test.stopTest();

On another note; should I name the relationship "Contact" rather than "Awarded To"? What is the best practice convention here?

1
  • only set the comm.Awarded_To__c is enough
    – m Peixoto
    Oct 22 '19 at 8:53
0

You shouldn't specify both __r and __c variants on a record like this. This is because the __r variant tells Saleforce that you want to associate a record by an External ID, while the __c variant tells Salesforce that you want to associate a record by ID. Consider this code:

Contact c = new Contact(LastName='Doe', Account=new Account(External_Id__c='Demo 123'));
insert c;

In this code, I create a new Contact that is linked to the Account with an External ID of 'Demo 123'. If there is not exactly one matching record, this code instead throws an exception.


In the case of the unit test, you ordinarily only need to set the __c value. There are times you might want to set the __r value instead, such as in a Visualforce page controller where the values for the related record are specified in the markup, and you want to emulate that in your unit test:

Account a = new Account(Name='Demo');
insert a;
Contact c = new Contact(AccountId=a.Id, LastName='Demo');
insert c;
Commission__c com = new Commission__c(Awarded_To__r=c, Amount__c=5000);
ApexPages.StandardController stdCtrl = new ApexPages.StandardController(com);
MyVFPageController controller = new MyVFPageController(stdCtrl);
// .. more logic here

Therefore, there are times you might want to initialize __r, or even both of them, but only when the code you're testing needs it, which is usually pretty rare.


On another note; should I name the relationship "Contact" rather than "Awarded To"? What is the best practice convention here?

The field's name should be a description of what its describing. As a standard system example, check out Contact.ReportsToId. Here, this field is referencing a Contact object, but we call it ReportsTo/ReportsToId. In the UI, the field's label is Reports To, and indicates the person's direct manager (at least, this is the intent of this field).

Often, the object name and field name will happen to correspond to each other (see Contact.AccountId as an example), but it doesn't need to be. I think the industry norm would be to call it AwardedTo__c (or Awarded_To__c), since that's is what the field is describing; the person to whom the commission was awarded to. It's typically better to have a descriptive name than one that describes the object you're referencing, especially if you'd otherwise have a discrepancy between the label and field name, or an ambiguous field label.

Imagine you're looking at a Commission record. Would it be clearer to say "Contact" or "Awarded To"? The former only describes that it's a contact record, but the latter informs the user that this commission was awarded to that contact. This is a much better description so users don't have to guess the intent.

Similarly, given a field label of "Awarded To", would it be better to call it Contact__c or Awarded_To__c? Any competent/experienced developer is going to naturally presume that the field is named AwardedTo__c or Awarded_To__c, but definitely not Contact__c.

You could do this, but the more "naming exceptions" you have, the harder it will be for developers to work with this later, as they'll have to consult the metadata/documentation to know what field they're looking for. It'd be best to have the name match the label.

2
  • Thank you @sfdcfox. Following on from this. I want to traverse the relationship from the commission object to its account parent object, to find its ID. How do I do this? I thought it should be commissionObject.Awarded_To__r.AccountId but it returning null for me.
    – gpcurran
    Oct 23 '19 at 14:50
  • @gpcurran Inside the unit test, assuming you specify just the __c field, the __r would not contain any data. You'd want to query the record first. You might want to post a new question, and perhaps we could help you out with your problem?
    – sfdcfox
    Oct 23 '19 at 19:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.