Class Name: TestDataFactory¶
Last Updated: 2025-10-22 Source Code: https://github.com/AANP-IT/I2C.Salesforce.Metadata/blob/STAGING/force-app/main/default/classes/TestDataFactory.cls
API Name: TestDataFactory Type: Test Utility Test Coverage: N/A (Test utility class)
Business Purpose¶
The TestDataFactory class provides centralized test data generation utilities for Apex test classes. This ensures:
- Consistent test data across all test classes
- Reduced code duplication in tests
- Easy maintenance of test record structures
- Support for Commerce Cloud and custom object testing
- Valid record creation with required fields populated
This is a foundational test utility class used throughout the test suite.
Class Overview¶
- Author: Ecaterina Popa
- Created: 07/21/2024
- Last Modified: 09/03/2024
- Scope:
@IsTest- Only available in test context - Key Responsibilities:
- Create Account records (Business and Person Accounts)
- Create Commerce Cloud objects (WebStore, WebCart, CartItem, Order, OrderSummary)
- Create Product2, Pricebook2, and PricebookEntry records
- Create custom objects (Membership__c, Subscription__c, PracticeSite__c, AANP_Event__c)
- Create User records for portal testing
- Support both insert and return patterns
Constants¶
private static final String COUNTRY = 'United States';
private static final String COUNTRY_CODE = 'US';
private static final String STATE = 'Alabama';
private static final String STATE_CODE = 'AL';
private static final String CITY = 'Fairfield';
private static final String ADDRESS = '5500 Myron Massey Blvd';
private static final String ZIP = '35064';
private static final String PREF_MAIL_ADDR = 'Home';
Purpose: Default address values for test records.
Public Methods¶
Account Methods¶
getAccountRecord (Simple)¶
Creates: Business Account with default values including Fellow fields.
Key Fields: - RecordType: 'Business_Account' - Phone: '+11234567890' Phone_Type__c: 'Mobile' - Fellow fields: Is_a_Fellow__c = true, Fellow_Designation__c = 'Employee' - Complete billing and shipping addresses
getAccountRecord (Parameterized)¶
public static Account getAccountRecord(String name, String phone, String city, String address, String zip, Boolean doInsert)
Creates: Business Account with custom values.
convertAccountToPersonAccount¶
Purpose: Converts Business Account to Person Account.
Issues/Concerns:
- ⚠️ Unused Parameter: conId parameter not used in implementation (line 103)
- ⚠️ Direct Conversion: Doesn't create PersonContact relationship
- ✅ RecordType Switch: Changes RecordType to 'PersonAccount'
Contact Methods¶
getContactRecord¶
Creates: Contact with unique email and mailing address.
Key Feature: Uses System.now().millisecond() for unique emails.
User Methods¶
getPortalUser¶
Purpose: Creates portal user for Experience Cloud testing.
Process: 1. Creates Business Account 2. Creates Contact 3. Converts to Person Account 4. Creates User with 'AANP External Identity User' profile
Issues/Concerns: - ⚠️ Complex Setup: Multiple DML operations (Account, Contact, Account update, User) - ⚠️ Profile Dependency: Hardcodes 'AANP External Identity User' profile - ✅ Unique Username: Uses timestamp for uniqueness
Utility Methods¶
getRandomNumber¶
Purpose: Generates random numeric string with leading zeros.
Example: getRandomNumber(8) → "03847562"
Issues/Concerns: - ✅ Left Padding: Maintains consistent length with leading zeros - ✅ Unique Values: Uses Math.Random() for uniqueness
Commerce Cloud Methods¶
WebStore Objects¶
getWebStore: Creates WebStore (Type: 'B2C')
getWebCart: Creates WebCart with Active status
getCartDeliveryGroup: Creates CartDeliveryGroup with default address
getCartItems: Creates 2 CartItem records at $100 each
Product and Pricing¶
getProduct: Creates single Product2 with random SKU
getProductsList: Creates multiple Product2 records (family: 'Memberships')
getShippingProduct: Creates 'Shipping Charge' product
getStandardPricebook: Returns Test.getStandardPricebookId()
getWebStorePricebook: Creates custom pricebook with Type__c
getPricebookEntry: Creates PricebookEntry at $100
Order Objects¶
getOrder: Creates Commerce Order (RecordType: 'Commerce Order')
getDigitalOrderDeliveryMethod: Creates digital delivery method
getOrderDeliveryGroup: Creates OrderDeliveryGroup with default address
getOrderItem: Creates OrderItem and activates parent Order
getOrderSummary: Creates OrderSummary via ConnectApi
getFulFillOrder: Creates FulfillmentOrder via ConnectApi
getOrderPaymentSummary: Creates OrderPaymentSummary via ConnectApi
getPayment: Creates Payment (Status: 'Draft', Amount: $100)
Custom Object Methods¶
getMembership¶
Creates: Membership__c linked to OrderItem with 1-year duration.
createSubscription¶
Creates: Active Subscription__c with 12-month duration and auto-renewal.
createPracticeSite¶
Creates: Complete PracticeSite__c with all optional fields populated.
Key Fields: Address, phones, website, age groups, clinical focus, payors, etc.
createAANPEvents¶
public static List<AANP_Event__c> createAANPEvents(Integer numEvents, Integer daysFromToday, Integer externalId, Boolean doInsert)
Creates: Multiple AANP_Event__c records with sequential dates.
Features:
- Alternates between 'In-person' and 'Virtual' types
- Sequential event IDs starting from externalId
- Registration enabled by default
createAANPEventAttendees¶
public static List<AANP_Event_Attendee__c> createAANPEventAttendees(List<AANP_Event__c> events, Id personAccountId, Boolean doInsert, Integer startingEventAttendeeId, Integer accountExternalId)
Creates: Event attendee records for each event.
Buyer Account Methods¶
getBuyerAccount¶
Purpose: Queries or creates BuyerAccount.
Issues/Concerns: - 🚨 Query in Test Method: Queries BuyerAccount instead of always creating (line 518) - ⚠️ doInsert Logic: Only inserts if query returns empty AND doInsert=true - ⚠️ Return Empty Element: Returns buyerAccs[0] which could be empty list
Correct Implementation:
public static BuyerAccount getBuyerAccount(Boolean doInsert, String accId) {
BuyerAccount ba = new BuyerAccount(
BuyerId = accId,
Name = 'Test Buyer',
IsActive = true
);
if (doInsert) {
insert ba;
}
return ba;
}
Promotion Methods¶
getPromotionTarget: Creates PromotionTarget (5% discount on product)
getPromotion: Creates Promotion (Name: 'SALE2024')
getCoupon: Creates Coupon linked to promotion
Design Patterns¶
- Factory Pattern: Static factory methods for creating test records
- Builder Pattern: Optional
doInsertparameter for flexibility - Consistent Naming:
get*prefix for single records,get*Listfor collections - Constants: Centralized default values
- Chaining: Methods can call other factory methods (e.g., getPortalUser)
Best Practices¶
✅ Good Practices¶
- doInsert Parameter: Allows creating records without DML for performance
- Unique Values: Uses timestamps and random numbers for uniqueness
- Complete Records: Populates all required fields
- Centralized Constants: Easy to update address values
- ConnectApi Usage: Proper OrderSummary and FulfillmentOrder creation
⚠️ Areas for Improvement¶
- getBuyerAccount Query (line 518): Shouldn't query in test factory
- Unused Parameter (line 103):
conIdnot used in convertAccountToPersonAccount - Hardcoded Profile (line 139): 'AANP External Identity User' may not exist in all orgs
- Complex getPortalUser: Multiple DML operations reduce test performance
- No Validation: Doesn't validate required parameters
Usage Examples¶
Simple Account Creation¶
@IsTest
static void testExample() {
Account acc = TestDataFactory.getAccountRecord(true); // Inserted
Assert.isNotNull(acc.Id, 'Account should be inserted');
}
Order with OrderSummary¶
@IsTest
static void testOrderFlow() {
// Setup
Pricebook2 pb = TestDataFactory.getStandardPricebook();
Product2 prod = TestDataFactory.getProduct(true);
PricebookEntry pbe = TestDataFactory.getPricebookEntry(true, prod, pb);
Order order = TestDataFactory.getOrder(true, pb);
OrderDeliveryMethod odm = TestDataFactory.getDigitalOrderDeliveryMethod(true);
OrderDeliveryGroup odg = TestDataFactory.getOrderDeliveryGroup(true, odm, order);
OrderItem item = TestDataFactory.getOrderItem(true, prod, odg, order, pbe);
// Create OrderSummary
String osId = TestDataFactory.getOrderSummary(order.Id);
Assert.isNotNull(osId, 'OrderSummary should be created');
}
Bulk Products¶
@IsTest
static void testBulkProducts() {
List<Product2> products = TestDataFactory.getProductsList(true, 100);
Assert.areEqual(100, products.size(), 'Should create 100 products');
}
Dependencies¶
Salesforce Objects¶
- Standard Objects: Account, Contact, User, Product2, Pricebook2, PricebookEntry, Order, OrderItem, OrderSummary, etc.
- Custom Objects: Membership__c, Subscription__c, PracticeSite__c, AANP_Event__c, AANP_Event_Attendee__c
Profiles & RecordTypes¶
- Profile: 'AANP External Identity User', 'System Administrator'
- RecordType: 'Business_Account', 'PersonAccount', 'Commerce Order'
ConnectApi¶
- ConnectApi.OrderSummaryCreation
- ConnectApi.FulfillmentOrder
- ConnectApi.OrderPaymentSummary
Pre-Go-Live Concerns¶
🚨 CRITICAL¶
- getBuyerAccount Query (line 518): Queries in test method
- Remove query logic, always create new record
- Could cause test failures if buyer account exists
MEDIUM¶
- Unused Parameter (line 103): conId parameter never used
- Remove or implement functionality
- Hardcoded Profile (line 139): May not exist in all orgs
- Add null check or make profile name configurable
LOW¶
- Complex getPortalUser: Multiple DML operations slow tests
- Consider lighter version for performance
Changes & History¶
| Date | Author | Description |
|---|---|---|
| 07/21/2024 | Ecaterina Popa | Initial implementation |
| 09/03/2024 | Ecaterina Popa | Last modification |
Documentation Status: ✅ Complete Code Review Status: ⚠️ HIGH - Fix getBuyerAccount query logic Test Coverage: N/A (Test utility class) Usage: Used across all test classes in org