Last active
August 29, 2015 13:58
-
-
Save alan-morey/b869102440198f1d36f1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Salesforce does not allow the ability to write to certain SObject fields | |
* such as LastModifiedDate, CreatedDate etc. Even if those objects are | |
* not going to be inserted into the DB. This makes testing around these | |
* fields difficult as we always need to hit the database to load these values | |
* and it's not possible to inject the values you require. | |
* | |
* This method gets around that limitation by using JSON. We first create | |
* a representation of the data as a map of fields/values pairs. Then we | |
* transform the map into a JSON representation. This respresentation includes | |
* some metadata automatically to help the deserialization. Then we | |
* pass the JSON string back into the Json.deserializer and it writes the values | |
* to the fields for us as expected. | |
* | |
* Note: If we were to try to insert this object we would encounter an excecption | |
* as the field would be non-writable at the DB level. | |
*/ | |
public class TestSobjectBuilder { | |
public static final String ID_FIELD = 'Id'; | |
Map<String, Object> data = new Map<String, Object>(); | |
Type sObjectClassType; | |
SObjectType sObjectType; | |
public TestSobjectBuilderException extends Exception {} | |
public TestSobjectBuilder(Type sObjectClassType) { | |
this.sObjectClassType = sObjectClassType; | |
sObjectType = ((SObject) sObjectClassType.newInstance()).getSObjectType(); | |
} | |
public TestSObjectBuilder addMockId() { | |
return add(ID_FIELD, mockId(sObjectType)); | |
} | |
public TestSObjectBuilder add(SObjectField field, String value) { | |
return add(String.valueOf(field), value); | |
} | |
public TestSobjectBuilder add(String field, String value) { | |
data.put(field, value); | |
return this; | |
} | |
public TestSobjectBuilder addAll(Map<SObjectField, String> valuesByFieldName) { | |
for (SObjectField f : valuesByFieldName.keySet()) { | |
add(f, valuesByFieldName.get(f)); | |
} | |
return this; | |
} | |
public TestSobjectBuilder addAll(Map<String, String> valuesByFieldName) { | |
data.putAll((Map<String, Object>) valuesByFieldName); | |
return this; | |
} | |
public Object build() { | |
data.put('attributes', buildAttributes(sObjectType, (Id) data.get(ID_FIELD))); | |
String jsonData = Json.serialize(data); | |
return Json.deserialize(jsonData, sObjectClassType); | |
} | |
Map<String, String> buildAttributes(SObjectType soType, Id id) { | |
String type = String.valueOf(soType); | |
Map<String, String> attrs = new Map<String, String> { 'type' => type }; | |
if (id != null) { | |
attrs.put('url', String.format( | |
'/services/data/v29.0/sobjects/{0}/{1}', | |
new String[] { type, id } | |
)); | |
} | |
return attrs; | |
} | |
@TestVisible | |
static Id mockId(SobjectType sot) { | |
String prefix = sot.getDescribe().getKeyPrefix(); | |
if (String.isBlank(prefix)) { | |
throw new TestSobjectBuilderException('No Key Prefix could be determined for SObjectType: ' + String.valueOf(sot)); | |
} | |
return prefix + '000000000000AAA'; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@isTest | |
class TestSobjectBuilderTests { | |
static final String ISO_DATE_TIME = 'yyyy-MM-dd\'T\'HH:mm:ss.SSSZ'; | |
static final Integer MILLIS_PER_SECOND = 1000; | |
static TestSobjectBuilder builder; | |
@isTest static void build_WhenGivenAccountTypeAndNoAddedFields() { | |
Account actual = (Account) new TestSobjectBuilder(Account.class).build(); | |
System.assertNotEquals(null, actual); | |
} | |
@isTest static void build_WhenGivenAccountTypeAndAddIdField() { | |
Id expectedId = TestSobjectBuilderTests.mockId(Account.sObjectType); | |
Account actual = (Account) new TestSobjectBuilder(Account.class).add('id', expectedId).build(); | |
System.assertEquals(expectedId, actual.id); | |
} | |
@isTest static void build_WhenGivenAccountTypeAndAddedIdAndNonWritableFields() { | |
Id expectedId = TestSobjectBuilderTests.mockId(Account.sObjectType); | |
DateTime expectedLastModifiedDate = DateTime.now(); | |
Id expectedLastModifiedById = UserInfo.getUserId(); | |
builder = new TestSobjectBuilder(Account.class); | |
Account actual = (Account) builder.add(Account.id, expectedId) | |
.add(Account.lastModifiedById, expectedLastModifiedById) | |
.add(Account.lastModifiedDate, expectedLastModifiedDate.formatGmt(ISO_DATE_TIME)) | |
.build(); | |
System.assertEquals(expectedId, actual.id); | |
System.assertEquals(expectedLastModifiedById, actual.lastModifiedById); | |
System.assertEquals(truncateMilliSeconds(expectedLastModifiedDate), actual.lastModifiedDate); | |
} | |
@isTest static void build_WhenGivenContactTypeAndAddAllFields() { | |
Id expectedId = TestSobjectBuilderTests.mockId(Contact.sObjectType); | |
String expectedFirstName = 'John'; | |
String expectedLastName = 'Doe'; | |
builder = new TestSobjectBuilder(Contact.class); | |
Contact actual = (Contact) builder.addAll(new Map<SObjectField, String> { | |
Contact.id => expectedId, | |
Contact.firstName => expectedFirstName, | |
Contact.lastName => expectedLastName | |
}).build(); | |
Assert.equals(expectedId, actual.id); | |
Assert.equals(expectedFirstName, actual.firstName); | |
Assert.equals(expectedLastName, actual.lastName); | |
} | |
@isTest static void build_WhenGivenContactTypeAndAddAllStringFields() { | |
Id expectedId = TestSobjectBuilderTests.mockId(Contact.sObjectType); | |
String expectedFirstName = 'John'; | |
String expectedLastName = 'Doe'; | |
builder = new TestSobjectBuilder(Contact.class); | |
Contact actual = (Contact) builder.addAll(new Map<String, String> { | |
'ID' => expectedId, | |
'firstName' => expectedFirstName, | |
'LastName' => expectedLastName | |
}).build(); | |
System.assertEquals(expectedId, actual.id); | |
System.assertEquals(expectedFirstName, actual.firstName); | |
System.assertEquals(expectedLastName, actual.lastName); | |
} | |
@isTest static void build_WhenGivenContactTypeAndAddMockId() { | |
builder = new TestSobjectBuilder(Contact.class); | |
Contact actual = (Contact) builder.addMockId().build(); | |
System.assertNotEquals(null, actual.id); | |
} | |
static DateTime truncateMilliSeconds(DateTime dt) { | |
return DateTime.newInstance(MILLIS_PER_SECOND * (dt.getTime() / MILLIS_PER_SECOND)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment