4

I have some code that after inserting a task, calls an @future method to update some fields on the contact linked to that task (WhoId). This seems to work fine in sandbox, but I can't seem to get it confirmed in my unit test.

public static void handleAfterInsert(List<Task> newTasks) {
        Set<Id> taskIds = new Set<Id>();
        Set<Id> contactIds = new Set<Id>();
        Set<Id> accIds = new Set<Id>();
        for(Task t : newTasks){
            if(t.cas__Disposition__c != null){
                if(t.cas__Disposition__c != 'Transfer'){
                    accIds.add(t.WhatId);
                    contactIds.add(t.WhoId);
                    taskIds.add(t.Id);
                }
            }
        }
        if(taskIds.size()>0){
            asyncCASUpdates(accIds,contactIds,taskIds);
        }

@future private static void asyncCASUpdates(Set<Id> accIds,Set<Id> contactIds, Set<Id> taskIds){
        //... stuff with accounts
        //...
        //...now the contacts

    List<Contact> conToUpdate = [Select Id, User_Name__c, Session_Date__c, C_S_Disposition__c from Contact Where Id = :contactIds];
    List<Task> tasks = [Select Id, WhoId, cas__Disposition__c, ActivityDate, C_S_Caller__c from Task Where Id = :taskIds];
    Map<Id,Task> taskMap = new Map<Id,Task>();
    for(Task t : tasks){
        taskMap.put(t.WhoId,t);
    }
    for(Contact con : conToUpdate){
        if(taskMap.containsKey(con.Id)){
            con.User_Name__c = taskMap.get(con.Id).C_S_Caller__c;
            con.Session_Date__c = taskMap.get(con.Id).ActivityDate;
            con.C_S_Disposition__c = taskMap.get(con.Id).cas__Disposition__c;
            System.debug(con);
        }
    }


try{
            Database.update(conToUpdate,false);
        }
        catch(Exception e){
            //handle exception (it sends an email to Admins)
            //EDIT: ================       
            System.debug(e);
        }
    }

And the test code:

static testmethod void testCASApp(){
        User testAdmin = new User();
        Profile p = [Select ID from Profile Where Name = 'System Administrator'];
        UserRole r = [Select ID from UserRole Where Name = 'Management'];

        testAdmin.LastName = 'test';
        testAdmin.Alias = 'test';
        testAdmin.Email = '[email protected]';
        testAdmin.Username = '[email protected]';
        testAdmin.CommunityNickname = 'testtesttest';
        testAdmin.ProfileId = p.Id;
        testAdmin.UserRoleId = r.Id;
        testAdmin.TimeZoneSidKey = 'America/New_York';
        testAdmin.LocaleSidKey = 'en_US';
        testAdmin.EmailEncodingKey = 'UTF-8';
        testAdmin.LanguageLocaleKey = 'en_US';

        insert testAdmin;

        Test.startTest();
        System.runAs(testAdmin){
            Account testAcc = new Account(
                Name = 'Test'
            );
            insert testAcc;

            Contact testContact = new Contact(
                AccountId = testAcc.Id,
                LastName = 'Test'
            );
            insert testContact;

            Task testTask2 = new Task(
                WhoId = testContact.Id,
                Subject = 'Test',
                ActivityDate = Date.today(),
                OwnerId = testAdmin.Id,
                cas__Disposition__c = 'Meeting Scheduled'
            );
            insert testTask2;            
        }
        Test.stopTest();
        Contact[] result = [Select Id, Name, CallsThisStage__c, Session_Date__c, User_Name__c, C_S_Disposition__c from Contact];
        System.debug(result.size());
        System.assert(result[0].CallsThisStage__c == 1 && result[0].C_S_Disposition__c == 'Meeting Scheduled','Expected: Meeting Scheduled Actual: '+result[0]);
    }

My understanding is that I need to have my assertions after the Test.stopTest(); in order to force the asynchronous code to happen synchronously. However, the query is returning null values for the three fields I'm setting (User_Name__c,Session_Date__c,C_S_Disposition__c). According to the debug log, these values are set properly in the line immediately before the DML try/catch block in my @future method. The fields are visible to all users so it's not a field level security issue. What am I missing here?

1 Answer 1

0

I see that you have false in database.update method and hence its always good to check for error to figure DML went successful

Running test class with system.debug will confirm whether DML is having

 List<Database.SaveResult> updateResults;
    updateResults = Database.update(conToUpdate, false);
  for(Integer i=0;i<updateResults.size();i++){

        if (updateResults.get(i).isSuccess()){
            updateResults.get(i).getId();
        }
        else if (!updateResults.get(i).isSuccess()){
            // DML operation failed
            Database.Error error = updateResults.get(i).getErrors().get(0);
            String failedDML = error.getMessage();
            arudate.get(i);//failed record from the list
                                system.debug('Failed ID'+arudate.get(i).Id);

        }

    }
3
  • I added a debug to the catch block, and confirmed there is no exception thrown on Database.update Commented Apr 29, 2015 at 19:39
  • 1
    @ToddSprinkel, Mohith -- putting try-catch around Database.update with allOrNothing=false will not catch exception - you have to inspect the isSuccess() within the result of Database.Update(..), namely an array of database.saveResult.
    – cropredy
    Commented Apr 30, 2015 at 1:26
  • @crop1645 Great points .There is no sense with database.update method with false attribute Commented Apr 30, 2015 at 1:43

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .