Skip to content

Commit 54e26bf

Browse files
committed
documentation update
1 parent a2f7b82 commit 54e26bf

File tree

14 files changed

+484
-69
lines changed

14 files changed

+484
-69
lines changed

website/docs/cache/basic-features.md

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -100,22 +100,22 @@ public inherited sharing class SOQL_CachedProfile extends SOQLCache implements S
100100
**Usage Example:**
101101

102102
```apex title="Cached Selector Usage"
103-
// Get single profile from cache
103+
// Get single profile
104104
Profile adminProfile = (Profile) SOQL_CachedProfile.query()
105105
.byName('System Administrator')
106106
.toObject();
107107
108-
// Check if profile exists in cache
108+
// Check if profile with give criteria exists
109109
Boolean profileExists = SOQL_CachedProfile.query()
110110
.byName('Standard User')
111111
.doExist();
112112
113-
// Get profile ID from cache
113+
// Get profile ID from profile
114114
Id profileId = SOQL_CachedProfile.query()
115115
.byName('System Administrator')
116116
.toId();
117117
118-
// Extract specific field value from cache
118+
// Extract specific field value from profile
119119
String userType = (String) SOQL_CachedProfile.query()
120120
.byName('System Administrator')
121121
.toValueOf(Profile.UserType);
@@ -152,13 +152,10 @@ public with sharing class ExampleController {
152152
@AuraEnabled
153153
public static Id getSystemAdminProfileId() {
154154
// First call: executes initial query and caches all profiles
155-
return SOQL_CachedProfile.query()
155+
Profile adminProfile = (Profile) SOQL_CachedProfile.query()
156156
.byName('System Administrator')
157157
.toId();
158-
}
159158
160-
@AuraEnabled
161-
public static Id getStandardUserProfileId() {
162159
// Subsequent call: retrieves from cache, no database query
163160
return SOQL_CachedProfile.query()
164161
.byName('Standard User')
@@ -169,7 +166,7 @@ public with sharing class ExampleController {
169166

170167
## Field-Level Security
171168

172-
Unlike standard SOQL queries that use `WITH USER_MODE`, cached records require the `Security.stripInaccessible` method to enforce field-level security. This method works with both fresh query results and cached records.
169+
Unlike standard SOQL queries that use `WITH USER_MODE` all cached queries are executed `WITH SYSTEM_MODE`. To apply FLY to the cached records the `.stripInaccessible()` has to me invoked.
173170

174171
### stripInaccessible
175172

@@ -249,6 +246,8 @@ SOQLCache supports mocking for unit tests. You can mock either the cached result
249246

250247
### Mock Cached Results
251248

249+
To learn more about mocking in the cache module check the [Mocking](./examples/mocking.md) section.
250+
252251
```apex title="ExampleController.cls"
253252
public with sharing class ExampleController {
254253
public static Profile getSystemAdminProfile() {
@@ -401,7 +400,7 @@ SObject toObject() // Get single record
401400

402401
### Extract Record ID from Cache
403402

404-
**Traditional approach:**
403+
405404

406405
```apex title="Traditional SOQL"
407406
public static Id getSystemAdminProfileId() {
@@ -415,7 +414,7 @@ public static Id getSystemAdminProfileId() {
415414
}
416415
```
417416

418-
**With SOQLCache:**
417+
419418

420419
```apex title="With SOQLCache"
421420
public static Id getSystemAdminProfileId() {
@@ -427,7 +426,7 @@ public static Id getSystemAdminProfileId() {
427426

428427
### Extract Field Value from Cache
429428

430-
**Traditional approach:**
429+
431430

432431
```apex title="Traditional SOQL"
433432
public static String getSystemAdminUserType() {
@@ -441,7 +440,7 @@ public static String getSystemAdminUserType() {
441440
}
442441
```
443442

444-
**With SOQLCache:**
443+
445444

446445
```apex title="With SOQLCache"
447446
public static String getSystemAdminUserType() {
@@ -453,7 +452,7 @@ public static String getSystemAdminUserType() {
453452

454453
### Check Record Existence in Cache
455454

456-
**Traditional approach:**
455+
457456

458457
```apex title="Traditional SOQL"
459458
public static Boolean hasStandardUserProfile() {
@@ -467,7 +466,7 @@ public static Boolean hasStandardUserProfile() {
467466
}
468467
```
469468

470-
**With SOQLCache:**
469+
471470

472471
```apex title="With SOQLCache"
473472
public static Boolean hasStandardUserProfile() {

website/docs/cache/build-cached-selector.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ We don't force one approach over another; you can choose your own. Here are our
1212

1313
## A - Inheritance - extends SOQLCache, implements Interface + static (Recommended)
1414

15-
In this configuration, you can specify default fields, the cache storage type `cacheIn...` (Org Cache, Session Cache, or Apex transaction), and the time in hours before a refresh is required (`maxHoursWithoutRefresh`). Additionally, you can add an `initialQuery()` to prepopulate records in the cache, ensuring that subsequent queries retrieve records from the prepopulated set.
15+
In this configuration, you can specify default fields, the cache storage type `cacheIn...` (Org Cache, Session Cache, or Apex transaction), and the time in hours before a refresh is required (`maxHoursWithoutRefresh`). Additionally, you can add an `initialQuery()` to prepopulate records in the cache, ensuring that subsequent queries retrieve records from the prepopulated set. The `additionalAllowedConditionFields` allows you to specify which additional fields can be used in conditions besides `Id, Name, DeveloperName` and unique fields. You change it at your own risk, because non-unique fields cannot guarantee that the correct records are returned from the cache. More details [here](./advanced/design#cached-query-required-single-condition).
1616

1717
```apex
1818
public with sharing class SOQL_ProfileCache extends SOQLCache implements SOQLCache.Selector {
@@ -31,6 +31,12 @@ public with sharing class SOQL_ProfileCache extends SOQLCache implements SOQLCac
3131
return SOQL.of(Profile.SObjectType);
3232
}
3333
34+
public override List<SObjectField> additionalAllowedConditionFields() {
35+
return new List<SObjectField>{
36+
Profile.UserType // not unique field that !!!
37+
};
38+
}
39+
3440
public SOQL_ProfileCache byName(String name) {
3541
whereEqual(Profile.Name, name);
3642
return this;

website/docs/cache/examples/mocking.md

Lines changed: 150 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,49 +4,179 @@ sidebar_position: 25
44

55
# MOCKING
66

7-
Mock SOQL results in Unit Tests.
8-
9-
You need to mock external objects.
10-
11-
> In Apex tests, use dynamic SOQL to query external objects. Tests that perform static SOQL queries of external objects fail. ~ Salesforce
7+
Mock SOQLCache results in Unit Tests.
128

139
> **NOTE! 🚨**
1410
> All examples use inline queries built with the SOQL Lib Query Builder.
1511
> If you are using a selector, replace `SOQLCache.of(...)` with `YourCachedSelectorName.query()`.
1612
17-
## Mock Single Record
13+
## Single Record
14+
15+
Set mocking ID in Query declaration.
16+
17+
```apex title="Controller with Mock ID"
18+
public with sharing class ExampleController {
19+
public static Account getAccountByName(String accountName) {
20+
return (Account) SOQLCache.of(Account.SObjectType)
21+
.with(Account.Id, Account.Name, Account.BillingCity)
22+
.whereEqual(Account.Name, accountName)
23+
.mockId('ExampleController.getAccountByName')
24+
.toObject();
25+
}
26+
}
27+
```
28+
29+
Pass single SObject record to SOQLCache class, and use mock ID to target query to be mocked.
30+
31+
```apex title="Unit Test with Single Record Mock"
32+
@IsTest
33+
public class ExampleControllerTest {
34+
private static final String TEST_ACCOUNT_NAME = 'MyAccount 1';
35+
36+
@IsTest
37+
static void getAccountByName() {
38+
SOQLCache.mock('ExampleController.getAccountByName')
39+
.thenReturn(new Account(Name = TEST_ACCOUNT_NAME));
40+
41+
Test.startTest();
42+
Account result = ExampleController.getAccountByName(TEST_ACCOUNT_NAME);
43+
Test.stopTest();
44+
45+
Assert.areEqual(TEST_ACCOUNT_NAME, result.Name);
46+
}
47+
}
48+
```
49+
50+
During execution SOQLCache will return record that was set by `.thenReturn` method.
51+
52+
## No Results
53+
54+
```apex title="Controller for No Results Example"
55+
public with sharing class ExampleController {
56+
public static Account getAccountByName(String accountName) {
57+
return (Account) SOQLCache.of(Account.SObjectType)
58+
.with(Account.Id, Account.Name, Account.BillingCity)
59+
.whereEqual(Account.Name, accountName)
60+
.mockId('ExampleController.getAccountByName')
61+
.toObject();
62+
}
63+
}
64+
```
65+
66+
Pass an empty list: `.thenReturn(new List<Type>())`;
67+
- When `.toObject()` is invoked, it will return `null`.
68+
69+
This behavior will be the same as it is during runtime.
70+
71+
```apex title="Unit Test with Empty List Mock"
72+
@IsTest
73+
public class ExampleControllerTest {
74+
private static final String TEST_ACCOUNT_NAME = 'MyAccount 1';
75+
76+
@IsTest
77+
static void getAccountByName_NoResults() {
78+
SOQLCache.mock('ExampleController.getAccountByName')
79+
.thenReturn(new Account()); // Empty record
80+
81+
Test.startTest();
82+
Account result = ExampleController.getAccountByName(TEST_ACCOUNT_NAME);
83+
Test.stopTest();
84+
85+
Assert.isNull(result?.Name);
86+
}
87+
}
88+
```
89+
90+
## Parent Relationship
91+
92+
Set mocking ID in Query declaration for queries with parent relationships.
93+
94+
```apex title="Controller with Parent Relationship Query"
95+
public with sharing class ExampleController {
96+
public static Account getAccountWithOwnerInfo(Id accountId) {
97+
return (Account) SOQLCache.of(Account.SObjectType)
98+
.with(Account.Id, Account.Name)
99+
.with('Owner', User.Name, User.Email)
100+
.with('Owner.Profile', Profile.Name)
101+
.whereEqual(Account.Id, accountId)
102+
.mockId('ExampleController.getAccountWithOwnerInfo')
103+
.toObject();
104+
}
105+
}
106+
```
107+
108+
Create mock data with parent relationship structure.
109+
110+
```apex title="Unit Test with Parent Relationship Mock"
111+
@IsTest
112+
public class ExampleControllerTest {
113+
@IsTest
114+
static void getAccountWithOwnerInfo() {
115+
Account mockAccount = new Account(
116+
Id = '001000000000001',
117+
Name = 'Test Account',
118+
Owner = new User(
119+
Id = '005000000000001',
120+
Name = 'John Doe',
121+
Email = '[email protected]',
122+
Profile = new Profile(
123+
Name = 'System Administrator'
124+
)
125+
)
126+
);
127+
128+
SOQLCache.mock('ExampleController.getAccountWithOwnerInfo')
129+
.thenReturn(mockAccount);
130+
131+
Test.startTest();
132+
Account result = ExampleController.getAccountWithOwnerInfo('001000000000001');
133+
Test.stopTest();
134+
135+
Assert.isNotNull(result);
136+
Assert.areEqual('Test Account', result.Name);
137+
Assert.areEqual('John Doe', result.Owner.Name);
138+
Assert.areEqual('[email protected]', result.Owner.Email);
139+
Assert.areEqual('System Administrator', result.Owner.Profile.Name);
140+
}
141+
}
142+
```
143+
144+
## With Static Resource
18145

19146
Set mocking ID in Query declaration.
20147

21-
```apex
148+
```apex title="Controller with Static Resource Query"
22149
public with sharing class ExampleController {
23-
public static Account getAccount(Id accountId) {
24-
return (Account) SOQL.of(Account.SObjectType)
25-
.with(Account.BillingCity, Account.BillingCountry)
26-
.byId(accountId)
27-
.mockId('ExampleController.getAccount')
150+
public static List<Account> getAccountsByIndustry(String industry) {
151+
return SOQLCache.of(Account.SObjectType)
152+
.with(Account.Id, Account.Name, Account.Industry)
153+
.whereEqual(Account.Industry, industry)
154+
.allowFilteringByNonUniqueFields()
155+
.mockId('ExampleController.getAccountsByIndustry')
28156
.toObject();
29157
}
30158
}
31159
```
32160

33-
Pass single SObject record to SOQL class, and use mock ID to target query to be mocked.
161+
Pass records from Static Resource to SOQLCache class, and use mock ID to target query to be mocked.
34162

35-
```apex
163+
```apex title="Unit Test with Static Resource Mock"
36164
@IsTest
37165
public class ExampleControllerTest {
38166
@IsTest
39-
static void getAccount() {
40-
SOQLCache.mock('ExampleController.getAccount')
41-
.thenReturn(new Account(Name = 'MyAccount 1'));
167+
static void getAccountsByIndustry() {
168+
Account mockAccount = (Account) Test.loadData(Account.SObjectType, 'TestAccounts')[0];
169+
170+
SOQLCache.mock('ExampleController.getAccountsByIndustry')
171+
.thenReturn(mockAccount);
42172
43173
Test.startTest();
44-
Account result = (Account) ExampleController.getAccountByName('MyAccount 1');
174+
Account result = ExampleController.getAccountsByIndustry('Technology');
45175
Test.stopTest();
46176
47-
Assert.areEqual('MyAccount 1', result.Name);
177+
Assert.isNotNull(result);
48178
}
49179
}
50180
```
51181

52-
During execution Selector will return record that was set by `.thenReturn` method.
182+
During execution SOQLCache will return records from Static Resource that was set by `.thenReturn` method.

0 commit comments

Comments
 (0)