I am writting a test method, where I have to set closedate
of a case record to an old date.
I know, i can make Status
to "closed
", but it will give you close date as Today.
Is there any other way, where I can set the close date to an old date?
You should be able to do this, and set other system date fields, using JSON.deserialize(). For example (setting CreatedDate):
@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);
}
}
Above example and further detail here: https://help.salesforce.com/apex/HTViewSolution?id=000181873&language=en_US
CasSe
is a typo in the KB article; I also think that the type
and url
attributes are not relevant here when you explicitly deserialize into a Case object - they are more useful when deserializing into type = SObject or where you have related objects
I'm not sure you can set the ClosedDate on a case object in the database. Everything I google says that it should be possible and the Knowledge Article seems to suggest it is possible by using JSON.deserialize()
. But I have yet to find a working example.
Here's my proof that it doesn't work as advertised:
@isTest static void TestClosedDate() {
Case c = new Case();
c.Status = 'New';
insert c;
List<Case> cases = [select Id, ClosedDate from Case where Id = :c.Id];
System.debug(JSON.serialize(cases[0]));
String caseJson = JSON.serialize(c);
// Modify status to Closed and add ClosedDate to JSON
Datetime closedDate = Date.today().addDays(-1);
String closedDateStr = closedDate.formatGMT('yyyy-MM-dd\'T\'HH:mm:ss.SSS+0000');
caseJson = caseJson.replace('"New"', '"Closed","ClosedDate":"' + closedDateStr + '"');
System.debug(caseJson);
c = (Case) JSON.deserialize(caseJson, Case.class);
System.debug(JSON.serialize(c)); // verify deserialization worked
update c;
cases = [select Id, ClosedDate from Case where Id = :c.Id];
System.debug(JSON.serialize(cases[0]));
System.assertEquals(closedDate, cases[0].ClosedDate);
}
This outputs something like:
{"attributes":{"type":"Case","url":"/services/data/v45.0/sobjects/Case/5001X00000346IIQAY"},"Id":"5001X00000346IIQAY"}
{"attributes":{"type":"Case","url":"/services/data/v45.0/sobjects/Case/5001X00000346IIQAY"},"Status":"Closed","ClosedDate":"2019-06-13T00:00:00.000+0000","Id":"5001X00000346IIQAY"}
{"attributes":{"type":"Case","url":"/services/data/v45.0/sobjects/Case/5001X00000346IIQAY"},"Status":"Closed","ClosedDate":"2019-06-13T00:00:00.000+0000","Id":"5001X00000346IIQAY"}
{"attributes":{"type":"Case","url":"/services/data/v45.0/sobjects/Case/5001X00000346IIQAY"},"Id":"5001X00000346IIQAY","ClosedDate":"2019-06-14T19:30:33.000+0000"}
Assertion Failed: Expected: 2019-06-13 00:00:00, Actual: 2019-06-14 19:30:33
The first three lines are as expected. Reading the database after the update reveals that the ClosedDate in the database was set to the current time instead of the deserialized time we used in our code.
To be fair, the Knowledge Article says:
You can create sObjects in memory with arbitrary CreatedDate values by using JSON.deserialize.
In memory, sure! As proven by line 3 of the output above.
But the update
doesn't push what's in memory to the database, as shown on line 4. And the trigger code I'm trying to unit test really needs case objects in the database, not in memory.
If there are ways to do this, I'd love to learn about it. But for now, I'm going to assume it is simply not possible to create case objects in the database with a ClosedDate in the past.