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?