[SalesForce] Stumped by a SOQL query returning an empty list

I am writing a unit test for a new Apex method that I have tested declaratively and which works. I have methods to set up lots of rich data for testing on, but the unit test isn't covering a lot of the core code in my method.

Somehow, a SOQL query in the method is returning an empty list, but I've debugged a ton and verified that the data should be there.

public static void SetMarketingOppContactRoles(
        List<Opportunity> newlist, 
        Map<Id, Opportunity> newmap
        )
{
    Map<Id, Opportunity> openNewBizOpps = new Map<Id, Opportunity>();

    RecordType newBizRecordType = [SELECT Id FROM RecordType WHERE SObjectType = 'Opportunity' AND Name = 'New Business' LIMIT 1];

    //Find opps that qualify for contact role assignment
    for(Opportunity o:newList)
    {
        if(!o.isClosed && o.RecordTypeId == newBizRecordType.id)
            openNewBizOpps.put(o.id, o);
    }

    //If there's nothing to do, quick exit.
    if(openNewBizOpps.keyset().size() == 0) return;

    //Collect ids of all parent accounts to opps that need crs created
    Set<Id> accountIds = new Set<Id>();
    for(Opportunity o:openNewBizOpps.values())
    {
        if(!accountIds.contains(o.AccountId)) accountIds.add(o.AccountId);
    }

    //Query for all contacts on these accounts
    Map<Id, Contact> contacts = new Map<Id, Contact>([SELECT Id, AccountId FROM Contact WHERE AccountId IN :accountIds]);

...

I've done a ton of debugging and verified that the test data is being inserted with contacts and opps under the same accounts, i.e. that the accountIds set is being filled and that there are contacts that have been created beforehand with AccountIds that are in that set.

Why would the query be returning empty???

Edit: here are the methods that create the test data:

public static Map<String, List<SObject>> insertTestData_AccountsAndOpportunities(Integer numberOfAccounts, Integer numberOfOppsPerAccount) 
{
    if(!Test.isRunningTest()) return NULL;

    //Create lists of values for Opp fields
    RecordType newBizRecordType = [SELECT Id FROM RecordType WHERE SObjectType = 'Opportunity' AND Name = 'New Business' LIMIT 1];
    RecordType renewalRecordType = [SELECT Id FROM RecordType WHERE SObjectType = 'Opportunity' AND Name = 'Renewal' LIMIT 1];
    List<ID> recordTypes = new List<ID>{newBizRecordType.id, renewalRecordType.id};

    List<Profile> aeProfiles = [SELECT Id FROM Profile WHERE Name LIKE 'Account Executive%'];
    List<Profile> renewalsrepProfiles = [SELECT Id FROM Profile WHERE Name LIKE 'Renewals%'];

    Set<Id> aeProfileIds = new Set<Id>();
    Set<Id> renewalsrepProfileIds = new Set<Id>();

    for(Profile p : aeProfiles) aeProfileIds.add(p.id);
    for(Profile p : renewalsrepProfiles) renewalsrepProfileIds.add(p.id);

    User activeAE = [SELECT Id FROM User WHERE isActive = TRUE AND ProfileId IN :aeProfileIds LIMIT 1];
    User renewalsRep = [SELECT Id FROM User WHERE isActive = TRUE AND ProfileId IN :renewalsrepProfileIds LIMIT 1];
    List<ID> oppOwners = new List<ID>{activeAE.id, renewalsRep.id};

    List<String> leadSources = new List<String>{'Inbound','Outbound'};
    List<String> marketingLeadSources = new List<String>{'Advertising','Directories','Direct Traffic','Earned Media','eBlasts','Greenhouse Events','List Purchase','Paid Content ','Paid Search','PR','Search','Social Media','Trade Show','Webinar','Lead Buy','Resources Section'};

    List<String> stages = new List<String>{'Discovery', 'Awaiting Renewal', 'Closed Won', 'Closed Won'};
    List<Date> closeDates = new List<Date>{system.today() + 30, system.today() + 30, system.today(), system.today()};



    List<Account> accounts = new List<Account>();
    List<Opportunity> opps = new List<Opportunity>();

    Set<String> accountNames = new Set<String>();


    for(Integer i = 0; i < numberOfAccounts; i++)
    {
        String accountName = 'Account' + String.valueOf(Math.random()).left(20);
        accountNames.add(accountName);

        accounts.add(
            new Account(
            Name = accountName,
            Type = 'Pipeline',
            NumberOfEmployees = i*50,
            Industry = 'Technology',
            Handover_notes__c = '.',
            Billing_Contact_Name__c = 'name',
            Billing_Contact_Email__c = 'foo@bar.com'
            )   
        );
    }

    insert accounts;

    Map<Id, Account> accountsMap = new Map<Id, Account>([SELECT Id, Name, Type FROM Account WHERE Name IN :accountNames]);

    for(Account a : accountsMap.values())
    {
        String accountxname = a.name;
        Id accountxid = a.Id;

        for(Integer n = 0; n < numberOfOppsPerAccount; n++)
        {
            opps.add( 
                new Opportunity(
                    AccountId = accountxid,
                    Name = accountxname + 'Deal',
                    RecordTypeID = recordTypes[math.mod(n,recordTypes.size())],
                    Amount = 10000,
                    CloseDate = closeDates[math.mod(n,closeDates.size())],
                    StageName = stages[math.mod(n,stages.size())],
                    OwnerId = oppOwners[math.mod(n,oppOwners.size())],
                    Initial_Appointment_Date__c = system.today() - 20,
                    Contract_Terms__c = 'None',
                    LeadSource = leadSources.get(math.mod(n,leadSources.size())),
                    Marketing_Lead_Source__c = marketingLeadSources.get(math.mod(n,marketingLeadSources.size())),
                    SBQQ__Contracted__c = FALSE
                )
            );
            system.debug('Added opp for account #' + String.valueOf(n) 
                + ', RecordTypeId = ' + recordTypes[math.mod(n,recordTypes.size())] 
                + ', StageName = ' + stages[math.mod(n,stages.size())] 
                + ', CloseDate = ' + String.valueOf(closeDates[math.mod(n,closeDates.size())]));
        }
    }

    insert opps;
    opps = [SELECT Id, AccountId, RecordTypeId, RecordType.Name, CloseDate, IsClosed FROM Opportunity WHERE Account.Name IN :accountsMap.keySet()];

    Map<String, List<SObject>> finalMap = new Map<String, List<SObject>>();
    finalMap.put('Account', accountsMap.values());
    finalMap.put('Opportunity',opps);

    return finalMap;
}


public static Map<String, List<SObject>> insertTestData_ContactsWithCampaignsAndCampaignMembers(List<Account> accountsToPopulate, Integer numberOfContactsPerAccount)
{
    if(!Test.isRunningTest()) return NULL;

    system.debug('accountsToPopulate = ' + accountsToPopulate);

    List<Campaign> campaigns = new List<Campaign>();
    List<Contact> contacts = new List<Contact>();
    List<CampaignMember> campaignMembers = new List<CampaignMember>();

    Set<String> contactNames = new Set<String>();

    campaigns.add(
        new Campaign(
            Name = 'TestCampaign',
            IsActive = TRUE,
            Type = 'Greenhouse Events'
        )
    );


    insert campaigns;

    campaigns = [SELECT ID, Name, IsActive FROM Campaign WHERE Name = 'TestCampaign'];

    Integer ind = 0;

    for (Account a : accountsToPopulate)
    {
        ID accountxid = a.id; 
        system.debug('iterating on accountsToPopulate; accountxid = ' + a.id);

        for(Integer i = 0;i<numberOfContactsPerAccount; i++)
        {
            String contactName = 'Contact' + String.valueOf(Math.random()).left(20);
            contactNames.add(contactName);

            contacts.add(
                new Contact(
                    FirstName = 'Foo',
                    LastName = contactName,
                    AccountId = accountxid
                )
            );
            system.debug('Added contact ' + String.valueOf(i) + ' for account # ' + String.valueOf(ind) + ' with ID ' + a.id);
        }
        ind++;
    }

    insert contacts;

    contacts = [SELECT Id, AccountId FROM Contact WHERE LastName IN :contactNames];

    system.debug('inserted test contacts: ' + contacts);

    List<String> statuses = new List<String>{'Attended','Attended On-Demand','Influenced','Sent'};

    Integer index = 0;
    Integer statusIndex = 0;

    for(Contact c : contacts)
    {
        if(math.mod(index,2) == 0) //Create a CampaignMember for every other contact
        {
            campaignMembers.add(
                new CampaignMember(
                    CampaignId = campaigns[0].id,
                    ContactId = c.id,
                    Status = statuses[math.mod(statusIndex, statuses.size())]
                )
            );

            system.debug('Created CM for contact index ' + String.valueOf(index) + '. Status = ' + statuses[math.mod(statusIndex, statuses.size())]);

            statusIndex++;
        }

        index++;
    }

    insert campaignMembers;

    campaignMembers = [SELECT Id, CampaignId, ContactId, Status FROM CampaignMember];

    Map<String, List<SObject>> finalMap = new Map<String, List<SObject>>();
    finalMap.put('Campaign',campaigns);
    finalMap.put('Contact',contacts);
    finalMap.put('CampaignMember',campaignMembers);

    return finalMap;
}

And here is the test itself:

@istest static void TestOpportunityContactRoles()
{
    User adminUser = [SELECT Id FROM User WHERE IsActive = TRUE AND Profile.Name = 'System Administrator' LIMIT 1];
    System.runAs(adminUser) {
        GHCustomServices.populateCustomSettings();
    }

    Map<String, List<SObject>> testAccountsOpps = GHCustomServices.insertTestData_AccountsAndOpportunities(20, 4);

    Map<String, List<SObject>> testContactsCampaignsCampaignMembers = GHCustomServices.insertTestData_ContactsWithCampaignsAndCampaignMembers(testAccountsOpps.get('Account'), 12);

    List<Opportunity> oppsToUpdate = testAccountsOpps.get('Opportunity');

    Test.startTest();
    //update twice to cover code that excludes contacts with existing ocrs
    update oppsToUpdate;
    update oppsToUpdate;
    Test.stopTest();



}

Best Answer

Can you please mention which SOQL is returning empty?

As I have seen your code the problem is in this line of insertTestData_AccountsAndOpportunities() method:

opps = [SELECT Id, AccountId, RecordTypeId, RecordType.Name, CloseDate, IsClosed FROM Opportunity WHERE Account.Name IN :accountsMap.keySet()];

The accountsMap contains (Id, Account) which is populated from this query:

Map<Id, Account> accountsMap = new Map<Id, Account>([SELECT Id, Name, Type FROM Account WHERE Name IN :accountNames]);

that's why it will return empty and you are putting this opps into the map below: finalMap.put('Opportunity',opps);

Let me know my guess is right?

Related Topic