0

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();



}
  • did you get Id's in the accountIds?and can you post your test data creation in test class? – Anurag Jun 8 '16 at 20:52
  • I just added the test code and methods that insert data. FWIW in my debugging I have verified that during execution of the insertTestData_ContactsWithCampaignsAndCampaignMembers() method, contacts are being created on the correct accounts. – OBerm Jun 8 '16 at 20:59
  • how about opportunities, are they getting created, because in the apex class you posted, seems like the opportunities are not existing? – Anurag Jun 8 '16 at 21:07
  • and the are the recordtypes same for the opportunits you are creating and the one you queries in apex class? – Anurag Jun 8 '16 at 21:09
  • 1
    Consider adding assert(s) into the test method to confirm the data has actually been inserted by the time you are at at key points in your logic. You may be surprised things are not as you are expecting/assuming . – CloudHugger Jun 8 '16 at 21:20
2

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?

| improve this answer | |
  • Hi Santanu, yes that was one problem that I've now fixed. With some additional digging I also discovered that I need to explicitly insert the available CampaignMemberStatus option for the test Campaigns, which I was not doing. – OBerm Jun 9 '16 at 14:25

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.