function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Marco PinderMarco Pinder 

Help with Test Method please

Hi,

 

I have written a trigger that creates a Task when a CampaignMember attends a specific event. The trigger works great and I am now writing my Test Method so that I can implement this code in our live org, however I am not a coder and not sure how to achieve this.

 

I have written a couple of triggers recently along with the Test Methods and received some excellent help from this board.

 

Below is the trigger and Test Method I need help with so any advice is much appreciated.

 

 

trigger PowerOf3 on CampaignMember (after insert, after update) {
    Set<Id> contactIds = new Set<Id>();

    for (CampaignMember cm : trigger.new){
        contactIds.add(cm.ContactId);
    }
    List<Contact> contacts = [
        SELECT Id, AccountId, OwnerId, Contact.Account.Id, Contact.Account.Name, Contact.Owner.Id
, Contact.Owner.Name
        FROM Contact 
        WHERE Id in :contactIds
    ];
    Map<String, Contact> contactMap = new Map<String, Contact>();
    for (Contact contact : contacts){
        contactMap.put(contact.Id, contact);
    }
    for (CampaignMember cm : trigger.new){
        Contact currentContact = contactMap.get(cm.ContactId);
        String campaignId = cm.CampaignId;
        String powerOf3Id = '701R0000000AJPBIA4';
        if (campaignId == powerOf3Id){
            if (cm.Status == 'Attended'){
                Task task = new Task();
                task.RecordTypeId = '012R00000004lckIAA';
                //Contact contact = [SELECT Id,AccountId,OwnerId FROM Contact WHERE Id = :cm.ContactId];
                task.WhoId = cm.ContactId;
                task.WhatId = cm.CampaignId;
                task.Priority = 'Normal';
                task.Status = 'Not Started';
                task.Subject = 'Power of 3 Follow Up';
                task.Type = 'Call - outbound';
                //Account account = [SELECT Id,Name FROM Account WHERE Id = :contact.AccountId];
                task.Client_Account_Name__c = currentContact.account.Name;
                //User user = [SELECT Id,Name FROM User WHERE Id = :contact.OwnerId];
                task.Contact_Owner__c = currentContact.owner.Name;
                String mappedUserId = '';
                if (currentContact.owner.Id == '00530000000gSl9'){
                    mappedUserId = '00530000000kvVm';                    
                } else if (currentContact.owner.Id == '00530000000kvVm'){
                    mappedUserId = '00530000000kvVm';
                } else if (currentContact.owner.Id == '00530000000iMq2'){
                    mappedUserId = '00530000000lcQ1';
                } else if (currentContact.owner.Id == '00530000000lcQ1'){
                    mappedUserId = '00530000000lcQ1';
                } else if (currentContact.owner.Id == '00530000000i4Dg'){
                    mappedUserId = '00550000001Cjog';
                } else if (currentContact.owner.Id == '00550000001Cjog'){
                    mappedUserId = '00550000001Cjog';
                } else if (currentContact.owner.Id == '00530000000i4Dt'){
                    mappedUserId = '00550000001Cjog';
                } else if (currentContact.owner.Id == '00530000000i4D4'){
                    mappedUserId = '00550000000mez5';
                } else if (currentContact.owner.Id == '00550000000mez5'){
                    mappedUserId = '00550000000mez5';
                } else {
                    mappedUserId = '00550000000mFkK';
                }
                task.OwnerId = mappedUserId;
                upsert task;
            }
        }   
    }
}

 

@isTest
private class PowerOf3Test{
    static testMethod void PowerOf3Test(){

    //Set up the User record
    User u = new User(Firstname='Test',LastName='Test',Username='test.test@test.com',Email='test.test@test.com',Alias='ttest',CommunityNickname='test.test',TimeZoneSidKey='GMT',LocaleSidKey='en_GB',EmailEncodingKey='ISO-8859-1',ProfileId='00e50000000yyaB',LanguageLocaleKey='en_US');
    insert u;

    //Set up the Contact record
    Contact c = new Contact(Firstname='Test',LastName='Test');
    insert c;

    //Set up the Campaign record
    Campaign cg = new Campaign(Name='Test');
    insert cg;

    //Set up the CampaignMember record
    CampaignMember cm = new CampaignMember(CampaignId = cg.id,ContactId=c.id,Status='Sent');
    upsert cm;
    
    //Set up the Task record
    Task t = new Task(Subject = 'Test');
    upsert t;
    
    //Cause the Trigger to execute
    cm.Status='Attended';
    upsert cm;

    //Verify that the results are as expected
    Contact c2 = [SELECT Id,AccountId,OwnerId FROM Contact WHERE Id=:cm.ContactId];
    Campaign cg2 = [SELECT Id FROM Campaign WHERE Id=:cg.Id];
    CampaignMember cm2 = [SELECT ContactId,CampaignId,Status FROM CampaignMember WHERE ContactId=:c.Id];
    public List<Task> gettask() {
        return [SELECT RecordTypeId,WhoId,WhatId,Priority,Status,Subject,Type,Client_Account_Name__c,Contact_Owner__c,OwnerId FROM Task WHERE RecordTypeId='012R00000004lckIAA' AND WhoId=:c.Id];
    }
    String mappedUserId='';
    if(c2.Id=='00530000000gSl9'){
        mappedUserId='00530000000kvVm';
    } else if (c2.Id=='00530000000kvVm'){
        mappedUserId='00530000000kvVm';
    } else if (c2.Id=='00530000000iMq2'){
        mappedUserId='00530000000lcQ1';
    } else if (c2.Id=='00530000000lcQ1'){
        mappedUserId='00530000000lcQ1';
    } else if (c2.Id=='00530000000i4Dg'){
        mappedUserId='00550000001Cjog';
    } else if (c2.Id=='00550000001Cjog'){
        mappedUserId='00550000001Cjog';
    } else if (c2.Id=='00530000000i4Dt'){
        mappedUserId='00550000001Cjog';
    } else if (c2.Id=='00530000000i4D4'){
        mappedUserId='00550000000mez5';
    } else if (c2.Id=='00550000000mez5'){
        mappedUserId='00550000000mez5';
    } else {
        mappedUserId='00550000000mFkK';
    }
    System.assertEquals(t2.RecordTypeId,'012R00000004lckIAA');
    System.assertEquals(t2.WhoId,c2.Id);
    System.assertEquals(t2.WhatId,cg2.Id);
    System.assertEquals(t2.Priority,'Normal');
    System.assertEquals(t2.Status,'Not Started');
    System.assertEquals(t2.Subject,'Power of 3 Follow Up');
    System.assertEquals(t2.Type,'Call - outbound');
    System.assertEquals(t2.Client_Account_Name__c,c2.AccountId);
    System.assertEquals(t2.Contact_Owner__c,c2.OwnerId);
    System.assertEquals(t2.OwnerId,mappedUserId);
    }
}

 Can anyone advise me on how the Test Method should be made please?

 

Thanks,

 

Marco

zachelrathzachelrath

First note on your code:

 

instead of doing this to create a Map of Contacts keyed by Id:

 

 

List<Contact> contacts = [
        SELECT Id, AccountId, OwnerId, Contact.Account.Id, Contact.Account.Name, Contact.Owner.Id
, Contact.Owner.Name
        FROM Contact 
        WHERE Id in :contactIds
    ];
    Map<String, Contact> contactMap = new Map<String, Contact>();
    for (Contact contact : contacts){
        contactMap.put(contact.Id, contact); 

Just build the Map at the same time you do your SOQL query:

 

Map<Id,Contact> contacts = new Map<Id,Contact>(
   [SELECT Id, AccountId, OwnerId, 
           Contact.Account.Id, Contact.Account.Name,
            Contact.Owner.Id, Contact.Owner.Name
     FROM Contact
    WHERE Id in :contactIds]
);

 This way, you have made your SOQL query AND built a Map in just 1 Script Statement, as opposed to in N Script Statements (which, if your Trigger is handling 10,000 Campaign Member records, could end up meaning N = 10,000).

 

Regards,

 

Zach

Marco PinderMarco Pinder

Thanks Zach, that's very helpful, I'll be sure to amend my code.

 

Any tips on how to test for the new Task that is being created when the trigger fires?

 

Thanks,

 

Marco

zachelrathzachelrath

Here's some general help for testing that a given Task was created correctly by the Trigger:

 

Right after you cause the Trigger to execute:

 

//Cause the Trigger to execute
    cm.Status='Attended';
    upsert cm;

 I would then query the Task object for all Tasks having WhoId set to the appropriate Contact Id and WhatId set to the appropriate Campaign Id (there should only be one such Task, I think), and then verify that the retrieved Task was created appropriately:

 

// Cause the Trigger to execute
cm.Status = 'Attended';
upsert cm;

// Verify that a new Task was created
List<Task> tasks =
  [select Id, WhoId, WhatId, Priority, Status, 
          Subject, Type,
          Client_Account_Name__c,
          Contact_Owner__c
   from Task
   where WhoId = :cm.ContactId
   and WhatId = :cm.CampaignId];

// Only one such Task should have been created
System.assertEquals(1, tasks.size(),'tasks.size()');

// Verify that the Task was created correctly
// by testing that its Fields equal what we expect them to equal
System.assertEquals('Call - outbound',tasks[0].Type,'tasks[0].Type');
System.assertEquals('Normal',tasks[0].Priority,'tasks[0].Priority');
....

 

However, in order to test all the different branches of your code (where the Owner Id is set differently depending on the Owner of the Campaign Member's Contact, you're going to have to do one of 2 things:

 

1. Have your test method create 8-9 different Test Contacts, with the Owner of each set to a different one of the 8-9 Owners you test for in your Trigger, and then create a corresponding Campaign Member record for each of these contacts. Then, you can do a Query for all Tasks where WhoId is equal to one of your Contact Ids, and you can verify that each Task's Owner was populated appropriately depending on the Contact Id.

2. Store the Contact Owner -to- Task Owner mappings in a separate SObject or Custom Setting, which you can query against in your Trigger as opposed to having to have the data all stored in if/else statements. This method would be cleaner, but isn't necessary.

 

 

Option 1 would look something like this:

 

 

Set<Id> contactOwnerIds = new Set<Id>{
   '00530000000gSl9',
   '00530000000kvVm',
   etc...
};

List<Contact> testContacts = new List<Contact>();

for (Id ownerId : contactOwnerIds) {
   // Create a new Contact for each Contact Owner Id
   // in our Set
   testContacts.add(new Contact(
       FirstName = 'Test',
       LastName = 'Contact',
       OwnerId = ownerId
   ));
}

insert testContacts;

// Verify that your Contacts were inserted...
// ....

List<CampaignMember> testMembers = new List<CampaignMember>();
Set<Id> contactIds = new Set<Id>();

//  Create a new Campaign Member for each of these Contacts,
// and add each Contact's Id to our list of Contact Ids
for (Contact c : testContacts) {
   contactIds.add(c.Id);
   testMembers.add(new CampaignMember(
       CampaignId = campaign.Id,
       ContactId  = c.Id,
       Status = 'Sent'
   ));
}

insert testMembers;

// Verify that your Campaign Members were inserted...
// ....

// Update the Status of each Campaign Member,
// to cause the Trigger to execute
for (CampaignMember cm : testMembers) {
   cm.Status = 'Attended';
}

upsert testMembers;

// Verify that a new Task was created for each Campaign Member
List<Task> tasks =
  [select Id, OwnerId, WhoId, WhatId, 
          Who.OwnerId,
          Priority, Status, 
          Subject, Type,
          Client_Account_Name__c,
          Contact_Owner__c
   from Task
   where WhoId in :contactIds
   and WhatId = :campaign.Id];

// One Task should have been created 
// for each of the Contact Owner Ids we specified
System.assertEquals(contactOwnerIds.size(), tasks.size(),'tasks.size()');

for (Task t : tasks) {
   // The Task's Owner should have been set
   // to the Owner of the Task's Related Contact
   System.assertEquals(t.Who.OwnerId,t.OwnerId,'t.OwnerId');
   System.assertEquals('Normal',t.Priority,'t.Priority');
   System.assertEquals('Not Started',t.Status,'t.Status');
   // ....
}

 Hope that helps!

Marco PinderMarco Pinder

Hi Zach,

 

Apologies for not replying sooner, I have had other items of work on my agenda.

 

I am still tackling the test class for this trigger but unfortunately get an error regarding the number of tasks created.

 

The line of code: System.assertEquals(1, tasks.size(),'tasks.size()');

 

Gives the error message: System.AssertException: Assertion Failed: tasks.size(): Expected: 1, Actual: 0

 

So it looks as though the task is not even being created!

 

Do you (or anyone else) have any advice please?

 

Thanks again,

 

Marco

Marco PinderMarco Pinder

In fact, ignore my previous post as I assume the task is not getting created because I am not specifying the Id of the Campaign (the trigger is expecting the campaign to have a particular Id).

 

However in the test class, I am unable to specify the Id of a campaign as it is not writeable on Insert or Upsert.

 

How can I define the Id of a campaign in the test class?

zachelrathzachelrath

You need to insert a test Campaign, and then retrieve its Id. The Id of a record is never updateable --- it is created when a record is first inserted.

 

So in your test code, create a test Campaign like this:

 

// Insert a test Campaign
Campaign testCampaign = new Campaign(
   Name = 'My Test Campaign',
   OtherField = '',
   AnotherField = '',
   etc...
);

// After this line is run, the Campaign will have an Id
insert testCampaign;

// Retrieve the Campaign's Id
Id testCampaignId = testCampaign.Id;

 

Marco PinderMarco Pinder

Hi Zach,

 

Thanks for your response again.

 

However, surely on creating the test Campaign, the Id assigned to it will not cause the trigger to fire when I create or edit a campaign member with the specific status as it requires a speciifc CampaignId too.

 

How would I get around this?

 

 

zachelrathzachelrath

Oh, that's right --- the whole point of your Trigger is to have different functionality based on predefined Campaign Ids, so making a test Campaign really doesn't make any sense here. Sorry, it's been a while since I first read this post.

 

What you want to do is to query for the Campaigns which are already in your database --- in general, you want to rely on record Names, not Ids, but in this case, you could just query for the Campaigns by Id, like so:

 

// Define the Campaign Ids that we're interested in
Set<Id> campaignIds = new Set<Id>{
   '123801820830',
   '293749273444',
   ......
};

// Query the database for the Campaigns we care about
Map<Id,Campaign> mapCampaigns = new Map<Id,Campaign>(
    [select id from Campaign where Id in :campaignIds]
);

// Now you can access a given Campaign's record by 
// looking it up in the map
Id marketingCampaignId = mapCampaigns.get('2374927349');

// Do something with the Campaign Id...