You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: website/docs/advanced-usage/mocking.md
+39-10Lines changed: 39 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -5,7 +5,7 @@ sidebar_position: 30
5
5
# Mocking
6
6
7
7
Mocking provides a way to substitute records from a database with some prepared data. Data can be prepared in the form of SObject records and lists in Apex code or Static Resource `.csv` file.
8
-
Mocked queries won't make any SOQLs and simply return data set in method definition, mock__will ignore all filters and relations__, what is returned depends __solely on data provided to the method__. Mocking is working __only during test execution__. To mock SOQL query, use `.mockId(id)` method to make it identifiable. If you mark more than one query with the same ID, all marked queries will return the same data.
8
+
Mocked queries won't make any SOQLs and simply return data set in method definition. Mock__will ignore all filters and relations__; what is returned depends __solely on data provided to the method__. Mocking works __only during test execution__. To mock a SOQL query, use the`.mockId(id)` method to make it identifiable. If you mark more than one query with the same ID, all marked queries will return the same data.
9
9
10
10
```apex title="ExampleController.cls"
11
11
public with sharing class ExampleController {
@@ -23,13 +23,42 @@ public with sharing class ExampleController {
23
23
}
24
24
```
25
25
26
-
Then in tests simply pass data you want to get from Selector to `SOQL.mock(id).thenReturn(data)` method. Acceptable formats are: `List<SObject>`or `SObject`. Then during execution Selector will return the desired data.
26
+
Then in tests simply pass data you want to get from the Selector to the `SOQL.mock(id).thenReturn(data)` method. Acceptable formats are: `List<SObject>`, `SObject`, `Integer` (for count queries), or `List<Map<String, Object>>` (for aggregate results). During execution, the Selector will return the desired data.
27
27
28
28
## Insights
29
29
30
+
### Mocking Stack Functionality
31
+
32
+
SOQL Lib implements a sophisticated mocking system that supports multiple sequential mocks for the same query identifier. This enables complex testing scenarios where the same query needs to return different results across multiple executions.
33
+
34
+
**How the Stack Works:**
35
+
36
+
Each call to `SOQL.mock(mockId)` creates a new mock entry and adds it to a list (stack) associated with that mock ID. When queries are executed:
37
+
38
+
-**Single Mock**: If only one mock exists for the ID, it's reused for all executions
39
+
-**Multiple Mocks**: Mocks are consumed in FIFO (First In, First Out) order - each execution removes and returns the first mock from the stack
// Fourth execution would fail - no more mocks available
57
+
```
58
+
30
59
### Id Field Behavior
31
60
32
-
The `Id` field is always included in mocked results, even if it wasn’t explicitly specified. This is designed to mirror standard SOQL behavior — Salesforce automatically includes the `Id` field in every query, even when it’s not listed in the `SELECT` clause.
61
+
The `Id` field is always included in mocked results, even if it wasn't explicitly specified. This is designed to mirror standard SOQL behavior — Salesforce automatically includes the `Id` field in every query, even when it's not listed in the `SELECT` clause.
33
62
34
63
```apex
35
64
List<Account> accounts = [SELECT Name FROM Account LIMIT 3];
@@ -95,14 +124,14 @@ for (Account mockedResult : result) {
95
124
In this case:
96
125
- Although `Description` and `Website` were present in the mocked data, they are removed because they weren’t part of the query.
97
126
- Only fields explicitly defined in `.with()` (plus `Id` by default) remain.
98
-
Account `Description` and `Website` are null, even though they were specified. Hovever SOQL specified only for `Account.Name`, so additional field are stripped.
127
+
Account `Description` and `Website` are null, even though they were specified. However, SOQL specified only `Account.Name`, so additional fields are stripped.
99
128
100
129
**Note:**
101
130
Currently, this field-stripping behavior applies only to simple fields (such as `Name`, `Description`, etc.) and subqueries. Additional subqueries are also removed — only the explicitly queried subqueries remain.
102
131
103
132
Relationship fields and queries using functions are not yet covered by this logic. This means that SOQL queries involving relationship records or functions (like `COUNT`, `AVG`) will return the exact mock defined in the unit test. This may be addressed in future enhancements.
104
133
105
-
### Queried Issued Count
134
+
### Queries Issued Count
106
135
107
136
Mocked queries in SOQL Lib are counted towards the SOQL query limit, just like real queries. If the number of issued queries exceeds the limit, SOQL Lib will throw:
108
137
@@ -179,7 +208,7 @@ private class ExampleControllerTest {
179
208
180
209
@IsTest
181
210
static void getPartnerAccountsCount() {
182
-
SOQL.setCountMock('mockingQuery', 2);
211
+
SOQL.mock('mockingQuery').thenReturn(2);
183
212
184
213
Integer result = SOQL.of(Account.sObjectType).count().mockId('mockingQuery').toInteger();
185
214
@@ -190,13 +219,13 @@ private class ExampleControllerTest {
190
219
191
220
## Sub-Query
192
221
193
-
To mock a sub-query we need to use deserialization mechanism. There are two approaches, using JSON string or Serialization/Deserialization.
194
-
Then after deserialization to desired SObjectType, pass the data to SOQL by calling `.mock` method.
222
+
To mock a sub-query, we need to use a deserialization mechanism. There are two approaches: using JSON string or Serialization/Deserialization.
223
+
After deserialization to the desired SObjectType, pass the data to SOQL by calling the`.mock` method.
195
224
196
225
197
226
_Using JSON String_
198
227
199
-
By passing simple String, it is possible to write non-writable fields, like `Name` on Contact object.
228
+
By passing a simple String, it is possible to write non-writable fields, like `Name` on the Contact object.
0 commit comments