Take the 2-minute tour ×
Salesforce Stack Exchange is a question and answer site for Salesforce administrators, implementation experts, developers and anybody in-between. It's 100% free, no registration required.

I have created an Apex Trigger that works exactly how I need it to within the sandbox. However, when I created the Apex Class and ran the test, I get a failing grade and am not sure how to troubleshoot my code.

Objective: Create two custom fields that will appear on the Task Page Layout, and will pull from the Contact Record (ie. Phone, Email already does this). The two fields are: MobilePhone & Title.

Apex Trigger shown below:

Trigger Task_Mobile on Task(before insert, before update){

Map<Id, List<Task>> whoIdsMap = new Map<Id, List<Task>>();

for(Task t : trigger.new){

    if(t.WhoId != null){

        if(!whoIdsMap.containsKey(t.WhoId)){

            List<Task> temp = new List<Task>();

            temp.add(t);

            whoIdsMap.put(t.WhoId, temp);
        }else{

            whoIdsMap.get(t.WhoId).add(t);
        }
    }
}


for(Contact con : [Select Id, Name,MobilePhone  from Contact where Id in :whoIdsMap.keySet()]){

    for(Task t :whoIdsMap.get(con.Id)){
        t.mobile__c = con.MobilePhone;
    }
}
for(Contact con : [Select Id, Name,Title  from Contact where Id in :whoIdsMap.keySet()]){

    for(Task t :whoIdsMap.get(con.Id)){
        t.title__c = con.Title;
}
}

Apex Class shown below:

@IsTest
public class TestTask_Mobile {

static testmethod void insertTask() {

    Task u = new Task();
    insert u;

    u.ownerID='005C0000004wuPO';
    u.Subject='Run Test Trigger';
    u.Status='Not Started';
    u.Priority='Normal';      
}
}

I would greatly appreciate any help/advice.

Thanks,

share|improve this question
add comment

3 Answers 3

up vote 3 down vote accepted

First off, your trigger has a couple areas of improvement:

  1. When you are creating your task list temp you are actually not bulkified correctly. Doing it the way you had it will overwrite the original task for a particular contact if there are multiple for that contact.
  2. You can do the mobile__c and title__c assignment in the same loop, which will just be more efficient

    Trigger Task_Mobile on Task(before insert, before update) {

    Map<Id, List<Task>> whoIdsMap = new Map<Id, List<Task>>();
    
    for (Task t : trigger.new) {
        if (t.WhoId != null) {
            if (!whoIdsMap.containsKey(t.WhoId)) {
                whoIdsMap.put(t.WhoId, new List<Task>());
            }
            whoIdsMap.get(t.WhoId).add(t);
        }
    }
    
    for (Contact con : [SELECT Id, Name, Title, MobilePhone FROM Contact WHERE Id IN :whoIdsMap.keySet()]) {
        for (Task t : whoIdsMap.get(con.Id)) {
            t.mobile__c = con.MobilePhone;
            t.title__c = con.Title;
        }
    }
    

    }

Secondly, as mentioned, you need to create your test data as part of your testMethod:

  1. You need to specify the task fields before the insertion of the task
  2. You need to create your test data (since you cannot use real data in tests, by default, you need to create the contact you are adding your task to, which will also require account creation since account is typically a required field for contact creation)
  3. You need to test your assumptions in your test class

    @IsTest public class TestTask_Mobile {

    static testmethod void insertTask() {
    
        User us = new User();
            us.FirstName = 'Test';
            us.LastName = 'User';
            // add whatever other fields are required for user creation here
        insert us;
    
        Account acc = new Account();
            acc.Name = 'Test Account';
            // add whatever other fields are required for account creation here
        insert acc;
    
        Contact con = new Contact();
            con.FirstName = 'Test'; // this assumes firstname is a required field on your contact records
            con.LastName = 'Contact'; // this assumes lastname is a required field on your contact records
            con.AccountId = acc.Id; // this assumes account is a required field on your contact records
            con.Title = 'Test Title'; // this is to validate your trigger
            con.MobilePhone = '1111111111'; // this is to validate your trigger
            // add whatever other fields are required for contact creation here
        insert con;
    
        Task u = new Task();
            u.ownerId = us.Id; // you've now successfully created your test user, time to use it on your new task
            u.whoId = con.Id; // you've now successfully created your test contact, time to use it on your new task
            u.Subject = 'Run Test Trigger';
            u.Status = 'Not Started';
            u.Priority = 'Normal';
        insert u;
    
        for (Task t : [SELECT Id, mobile__c, title__c FROM Task WHERE Id = :u]) {
            System.assertEquals('1111111111', t.mobile__c); // asserts that your test worked properly
            System.assertEquals('Test Title', t.title); // asserts that your test worked properly
        }
    
    }
    

    }

share|improve this answer
    
Nathan, I have updated my test class to exactly what yours shows; however, I am running into an error: "Compile Error: No such column 'MobilePhone' on entity 'Name'. If you are attempting to use a custom field, be sure to append the '__c' after the custom field name. Please reference your WSDL or the describe call for the appropriate names. at line 34 column 19. It is within the final "for" loop. There's an issue with 'who.MobilePhone', and 'who.Title'. –  ddean.au Apr 29 at 17:15
    
@ddean.au fixed... I guess you can't query fields on the who object without a black tab permission and using polymorphic TYPEOF designation. This way works, too, just a little more hard coded... –  Nathan Williams Apr 29 at 17:40
    
PERFECT!! Had to make a few minor tweaks, but that did it! I sincerely appreciate all of your help! –  ddean.au Apr 29 at 18:27
    
Everything worked great in sandbox. Class passed, and % coverage on trigger was 100%. However, I have tried deploying to Production and am receiving the following error: "System.DmlException: Insert failed. First exception on row 0; first error: DUPLICATE_USERNAME, Duplicate Username.<br>Another user has already selected this username.<br>Please select another.: [Username]", Failure Stack Trace: "Class.TestTask_Mobile.insertTask: line 18, column 1". The user's first name & last name are causing issues. Do you have any recommendations? –  ddean.au Apr 29 at 19:04
1  
Thank you @nathan-williams!! –  ddean.au Apr 29 at 22:13
show 1 more comment

In your test class, you need to create contact record such as,

Contact c = new Contact();
c.Title = 'Mr.';
c.lastname = 'test';
c.MobilePhone__c = '1231231234';
insert c;

then your task code follows,

Task u = new Task();
    insert u;

    u.ownerID='005C0000004wuPO';
    u.Subject='Run Test Trigger';
    u.Status='Not Started';
    u.Priority='Normal';

for the update you may need,

c.lastname = 'test 123';
c.MobilePhone__c = '1231231234';
update c;

Also, you should avoid hardcoding ownerId. Instead, you can create a user and assign the id here, just the same of what we did for contact.

share|improve this answer
add comment

You need to create test data in your test method. Tests don't have access to any records by default, so when your trigger fires when you insert the task in your test code, the Contact queries won't return anything.

In addition, if you want to test your trigger on update you should probably call update u in your test code.

Finally, you should probably have some System.asserts in the code to check that the values set on the task are what you expect.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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