CloudCraze Portal User Simulation and Storefront Setup for Tests

It's not uncommon for particular CloudCraze API calls to fail within a test because they aren't executed as a community portal user. One example of this, that we recently encountered, is with regard to the `ccrz.ccApiWishList.create()` method. In order to address scenarios like these we'd need to simulate a CloudCraze Community Portal User. There are a number of challenges that make creating a portal user difficult.

For one, `User.isPortalEnabled` cannot be assigned, since it isn’t writable. So even if a user record were created, that record wouldn’t be of any use without portal access. In addition, the task of creating the portal user also cannot be delegated to `Site.createExternalUser()` since this method returns a null user ID inside the context of a test. The `ccrz.ccAPIUser.registerUser()` method wraps the `Site.createExternalUser()` method, so it too, is not helpful  

Although this general problem can be dismissed by setting the `@IsTest(SeeAllData=true)` annotation to open access to existing records of portal users, in a typical unit testing scenario, it is assumed that the database remains isolated. In accordance with best practice, it’s always best to avoid using the `SeeAllData=true` annotation because it opens up the database for unexpected modification by tests. Also, writing tests that rely on the organization database does not ensure that the code will continue to work as expected when it is deployed to production, and run with a different database. This example code addresses how we implement this while keeping the database isolated from the tests `(SeeAllData=false)`:

Profile communityUserProfile = [SELECT Id FROM Profile WHERE Name='CloudCraze Customer Community User' LIMIT 1];

Map> testData = new Map>{
  ccrz.ccApiTestData.ACCOUNTGROUP_DATA => new Map{},
  ccrz.ccApiTestData.ACCOUNT_DATA => new Map{
    ccrz.ccApiTestData.ACCOUNT_LIST => new List>{
      new Map{
        'name' => 'testAccount1',
        'ccrz__dataId__c' => 'testAccount1'
  ccrz.ccApiTestData.CONTACT_DATA => new Map{
    ccrz.ccApiTestData.CONTACT_LIST => new List>{
      new Map{
        'ccrz__dataId__c' => 'testContact1',
        'account' => new Account(ccrz__dataId__c = 'testAccount1'),
        'email' => '',
        'lastName' => 'User1',
        'firstName' => 'Test1'
  ccrz.ccApiTestData.USER_DATA => new Map{
    ccrz.ccApiTestData.USER_LIST => new List>{
      new Map{
        'ccrz__dataId__c' => 'testUser1',
        'alias' => 'defusr1',
        'email' => '',
        'lastName' => 'User1',
        'firstName' => 'Test1',
        'languageLocaleKey' => 'fr',
        'localeSIDKey' => 'fr_FR',
        'emailEncodingKey' => 'UTF-8',
        'profileId' => communityUserProfile.Id,
        'username' => System.currentTimeMillis() + '',
        'ccrz__CC_CurrencyCode__c' => 'EUR',
        'contact' => new Contact(ccrz__dataId__c = 'testContact1'),
        'timezoneSIDKey' => 'GMT'

In brief: The `ccrz.ApiTestData()` API creates the Contact-Account-User records in a single go, with all the relationships handled. Tests also have access to profile records even without the `SeeAllData=true` attribute. So the profile can be queried and assigned to this newly created user. Then `Test.runAs(user)`, and build and initialize the context using the user and account records before the CCRZ method is invoked. When the method executes, the dependencies will be supplied by the context.

Ideally, this code should be invoked within the context of a system administrator with a role, using `Test.RunAs(user)`. This will avoid throwing the "portal account owner must have a role" exception if the tests are run by a user without a role. In our projects we abstract portal user creation into a utility handler that can be invoked inside the body an @IsTest or @TestSetup test method.

In addition, since some of the CCRZ global API methods require that you have a storefront bound to the context, if your tests are using `(SeeAllData=false)` - either implicitly or explicitly - you won’t have access to a storefront, and you’ll need to create one. Storefronts cannot be created using an object constructor, like with typical SObjects, since storefronts are not stored as SObjects. The ccrz.ccApiTestData API has support for storefront creation and configuration (even for configuring specific logic and service overrides for tests), and it’s advisable that you use it. Here’s a utility method that we use, specifically for this purpose:

public static Map createStorefront(String storefrontName) {
  Map> storefrontData = new Map > {
    ccrz.ccApiTestData.STOREFRONT_SETTINGS => new Map {
        storefrontName => new Map {
            'Allow_Anonymous_Browsing__c' => true,
            'Currencies__c' => 'USD',
            'Languages__c' => 'en_US',
            'Customer_Portal_Account_Name__c' => 'PortalAccount',
            'CustomerPortalAcctGroupName__c' => 'PortalAccount',
            'DefaultCurrencyCode__c' => 'USD',
            'DefaultLocale__c' => 'en_US',
            'InventoryCheckFlag__c' => false,
            'Quoting_Enabled__c' => true,
            'Skip_Tax_Calculation__c' => false,
            'Filter_Orders_Based_on_Owner__c' => true
  return ccrz.ccApiTestData.setupData(storefrontData);



View more blogs and tutorials about
Salesforce B2B Commerce Cloud


Learn more about our Salesforce B2B Commerce Cloud work

For thought leadership on B2B Commerce,
please click here for blogs and here for video.



Sitecore 144
Commerce 100
Web Development 100
Sitecore Commerce 83
Sitecore Experience Commerce 9 64
Sitecore Experience Commerce 59
Content Management 55
eCommerce 48
B2B eCommerce 42
Sitecore Experience Platform 39
Sitecore Platinum Partner 39
Architecture 34
Insite 29
User Experience 26
Strategy 22
B2C eCommerce 21
B2B Commerce Blogs 21
commerceconnect 21
CloudCraze 20
SaaS (Software as a Service) 20
Cloud 17
Commerce Server 17
Salesforce B2B Commerce Cloud 16
Mobile 13
Search 13
Plugins 12
Analytics 12
Application Development 12
Digital Transformation 11
Sitecore Symposium 11
Helix 10
Social 8
Business Process 7
Authentication 7
5 Reasons 7
BI and Big Data 6
Data Visualization 6
Sitecore Presentation 6
Coveo 6
NET Development 5
Microsoft Azure 5
Automation 5
Front-End Development 4
SaaS (Software as a Service) 4
Digital Strategy 4
Brightcove 4
Press Release 4
Avalara Tax 3
Sitecore Experience Accelerator (SXA) 3
Sitecore Layouts 3
Video 3
Multi-site 3
Multi-lingual 3
Accessibility 3
Habitat 3
Vault 3
Identity 2
Managed Services 2
Cryptocurrency 2
Sitecore Forms 2
Sitecore Experience Commerce 9 Promotions 2
Uncategorized 2
Conversational Commerce 2
Sitecore SaaS 2
Security 2
Unit Testing 2
Headless Architecture 2
Sitecore Experience Awards 2
Google 1
Content Delivery Network 1
Configure Price Quote 1
Blockchain 1
Coupons 1
Sitecore Rss 1
Artificial Intelligence 1
Machine Learning 1
Okta 1
RFP Process 1
Flex Accelerator for Sitecore 1
Reviews 1
Page Labels 1