2

Background

I have a custom object Contact_Coverage__c. I have a custom field Contact_Coverage__c added to the Activity standard object, with the child relationship name Activities__r. In general, I am able to find all associated Task records to a Contact_Coverage__c record using a standard relationship query, e.g.:

List<Contact_Coverage__c> ccList = [
    SELECT (
        SELECT Id
        FROM Activities__r
    )
    FROM Contact_Coverage__c
]
Integer howManyTasks = ccList.Activities__r.size();

Failing test

When I use this in a test, however, it is failing:

@isTest static void withCustomObject(){
    User u = [SELECT Id FROM User WHERE Id = :UserInfo.getUserId()];
    String random = String.valueOf(Math.random()); // to avoid dupes
    Account a = new Account(Name = 'Company, LLC' + random);
    insert a;
    Contact c = new Contact(LastName = 'Smith' + random, AccountId = a.Id);
    insert c;
    Contact_Coverage__c cc = new Contact_Coverage__c(
        Sales_Coverage__c = u.Id,
        Contact__c = c.Id,
        Coverage__c = '30'
    );
    insert cc;
    Task t = new Task(
        ActivityDate = System.Today(),
        Contact_Coverage__c = cc.Id
    );
    insert t;
    List<Task> tasks = [
        SELECT Contact_Coverage__c
        FROM Task
        WHERE Contact_Coverage__c = :cc.Id
    ];
    List<Contact_Coverage__c> contactCoverages = [
        SELECT (
            SELECT Id
            FROM Activities__r
        )
        FROM Contact_Coverage__c
    ];
    System.assertEquals(cc.Id, tasks[0].Contact_Coverage__c);
    System.assertEquals(1,contactCoverages[0].Activities__r.Size());
}

I would expect this to pass no problem. But the first assertEquals is passing, and the second assertEquals is failing.

Works fine with a Standard Object

When I do something very similar with Account instead of my custom object, it works as expected:

@isTest static void withStandardObject(){
    String random = String.valueOf(Math.random()); // to avoid dupes
    Account a = new Account(Name = 'Company, LLC' + random);
    insert a;
    Task t = new Task(
        ActivityDate = System.Today(),
        WhatId = a.Id
    );
    insert t;
    List<Task> tasks = [
        SELECT WhatId
        FROM Task
        WHERE WhatId = :a.Id
    ];
    List<Account> accounts = [
        SELECT (
            SELECT Id
            FROM Tasks
        )
        FROM Account
    ];
    System.assertEquals(a.Id, tasks[0].WhatId);
    System.assertEquals(1,accounts[0].Tasks.Size());
}

But passing in Execute Anonymous???

I would chalk this up to something wrong with my Custom Object, except that when I use this exact code (except not in a test method) in execute anonymous, both asserts pass! That's the reason I have the random string there, so I can run this without having to delete the newly generated Contact and Account each time.

Question

WTF is going on here? Is this a known quirk? Could it be some trigger or flow I don't know about (this is a 10 year old org and I've only been here a few months)? And if so, why the heck does it only happen in testing??

Note: This test as I'm providing it here obviously isn't testing anything, I just limited it down to the part that's confusing me.

  • 3
    if something works in exec anon but not in apex - it is most likely a version issue as exec anon always uses latest version – cropredy Feb 16 '18 at 20:27
  • @cropredy that solved it, if you'd like to make it an answer I can mark it correct. Specifically, the Apex class was set to API version 38.0, and when I set it to 42.0 it worked as expected (like exec anon) – Nathan Hinchey Feb 16 '18 at 20:34
  • You're comparing different child lists. One is Tasks (child type Task) and the other is a magical related list Activities__r (child types Task and Event). Have you tried using Activities on Account or tried Tasks__r on your custom object? – Adrian Larson Feb 16 '18 at 20:43
  • @AdrianLarson You can't add new custom fields directly to Task, which is why I added it on Activity. See this answer: success.salesforce.com/answers?id=90630000000gjGHAAY – Nathan Hinchey Feb 16 '18 at 21:53
3

When something works in execute anonymous but does not work in a testmethod, the typical reason is difference in version.

Execute Anonymous always operates in the latest version, including the sandbox preview version if yo are executing in such a sandbox.

Try aligning your testmethod and underlying classes to be the current version.

As for the commentary on custom fields on Tasks vs Activities - this is just a UI artifice presented by SFDC. Activity Custom Fields end up on the concrete Task and Event objects.

You can't do SOQL ...FROM Activity ..., instead, you do SOQL ...FROM Task... or ...FROM Event ...

You also have OOTB access to certain related lists for subselects

select ..., (select ID, ... FROM Events), ... FROM parentSobject
select ..., (select ID, ... FROM Tasks), ... FROM parentSobject
select ..., (select ID, ... FROM ActivityHistories), ... FROM parentSobject 

where parentSObject is any Sobject defined to support Activities.

plus any custom lookup relationships you defined on Task or Event to some specific parentSObject

| improve this answer | |

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.