3

My batch class query depends on LastModifiedDate of a record being atleast one day in the past.

How do I set this variable?

Alternatively, how do I change system date only in the test?

EDIT : I "solved" this by using actual data from the org.

2
  • 1
    for createddate you can do this easily Test.setCreatedDate(record.Id, DateTime.newInstance(2000,10,10)) Nov 3, 2016 at 7:07
  • This does not work. I did : insert rec; (your code); system.Test.startTest(); system.debug(rec.LastModifiedDate); bclass batch = new bclass(); id bid = database.executeBatch(batch);. The LastModifiedDate is still today's date.
    – fraglord
    Nov 3, 2016 at 7:24

4 Answers 4

7

There are 2 ways in which you can set system protected fields for test code coverage:

a) Using Test.loadData()

b) Using JSON.deserialize()

  1. Using Test.loadData.

In this option you will need to create a .csv file and enter the necessary data in the .csv file. Once the csv file is ready, upload the csv file as a static resource. [Attaching a sample .csv file with the article to try the below example]

a. Click Develop | Static Resources, and then New Static Resource. b. Name your static resource testCases. c. Choose the file you just created. d. Click Save.

Then Call Test.loadData in a test method to populate the test case data.

Code Example:

@isTest 
private class caseUtil{ 
static testmethod void testLoadData(){ 
List<sObject> ls = Test.loadData(Case.sObjectType,'testCases'); 

Case c = (Case)ls[0]; 

System.assert(ls.size() == 1); 
String cStatus = c.Status; 
DateTime cDate = c.CreatedDate; 

System.debug('Case Id: ' + c.Id); 
System.debug('Case Status: ' + cStatus); 
System.debug('Case Date: ' + cDate); 

c.status = 'New'; 

update c; 

System.debug('Case status: ' + c.status); 
} 
  1. Using JSON.deserialize You can create sObjects in memory with arbitrary CreatedDate values by using JSON.deserialize. This doesn't enforce the normal read-only field attributes that prevent you from setting a createdDate value.

Code Example:

@isTest 
private class CaseTest{ 
static testmethod void testLoadData(){ 
String caseJSON = '{"attributes":{"type":"CasSe","url":"/services/data/v25.0/sobjects/Case/500E0000002nH2fIAE"},"Id":"500E0000002nH2fIAE","Status":"Open","CreatedDate":"2012-10-04T17:54:26.000+0000"}'; 
Case c = (Case) JSON.deserialize(caseJSON, Case.class ); 
System.debug('Test case:' + c.createdDate); 
System.debug('Test caseId:' + c.Id); 
System.debug('Test caseStatus:' + c.status); 

Case c1 = new Case(); 
c1.Id = c.Id; 
c1.status = 'New'; 
update c1; 

System.debug('Test caseStatus1:' + c1.status); 

} 
} 

Source: https://help.salesforce.com/apex/HTViewSolution?id=000181873&language=en_US

1
  • 1
    Thanks, but where do I find the attributes data for my object? For example, what would be the type and url?
    – fraglord
    Nov 3, 2016 at 8:38
6

I like making my queries modifiable when I have to query on fields that are difficult to write to. Then when I run my test, I can just switch the query to look at a writeable field and set it, easy as that.

Batch

public with sharing class MyBatch implements Database.Batchable<SObject>
{
    @TestVisible static SObjectField dateField = MyObject__c.LastModifiedDate;

    public Database.QueryLocator start(Database.BatchableContext context)
    {
        return Database.getQueryLocator(
            'SELECT Id FROM MyObject__c WHERE ' + dateField + ' < TODAY'
        );
    }
    // implementation
}

Test

static testMethod void testBatch_FindRecords()
{
    MyBatch.dateField = MyObject__c.WriteableDateField__c;
    MyObject__c record = new MyObject__c(WriteableDateField__c = Date.today().addDays(-1));
    insert record;

    // run batch
    // assert on results
}
1

You can write in your code

if(Test.isRunningTest())
//Query based on other criteria
else
//Query one day old

However, it will be better, from all perspective, to store this input - -1 day - in custom settings (hierarchy). Then in your code use this custom settings.

Integer pastDays = customSettingName.getInstance().CustomSettingFieldName
DateTime myDate = system.now() - pastDays;
list<Account> l_accounts= [select id from account lastmodifiedDate > :myDate];

In the custom setting you'll setup it with value -1, but in the test class create the custom setting with value 0 or 1

1
  • ok this looks promising. I will try this and update status with the results
    – fraglord
    Nov 3, 2016 at 7:50
0

I am pretty sure in the past I have used test.loaddata to set the system date fields: https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_testing_load_data.htm

1
  • But as far as I can tell, you can neither edit nor load LastModifiedDate data.
    – fraglord
    Nov 3, 2016 at 7:28

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