Simplifying Sandbox Refreshes

At OpFocus, our Apex developers often work in newly refreshed Developer sandboxes. Often, though, we’re faced with a challenge: after a Developer sandbox is refreshed/activated, it lacks required reference data. Here are a few scenarios:

  • The org has a custom object that lists postal codes and their tax rates. An Opportunity trigger requires a Postal Code record before an Opportunity can be created, so before anyone can do any Opportunity work in the sandbox, somebody has to manually import a list of postal codes.
  • A company has a handful of business partners, represented by Account records. Before any testing can happen in the sandbox, somebody has to manually create Account records for these business partners.
  • A client with a custom product bundling solution has a custom object that identifies the Products that are associated with each bundle. Before anyone can test Opportunities in the sandbox, the Product Bundling object has to be manually imported into the sandbox.

Certainly, some of this reference data can be stored in custom settings, which is ideal because custom settings are automatically copied to newly refreshed sandboxes. However, we often find reference data is stored in custom objects, which are not automatically copied to new Developer sandboxes. In fact, some of our clients have so much reference data that they avoid refreshing sandboxes whenever possible, with the result that developers may be working in sandboxes that are months or even years out of sync with Production.

Fortunately, Spring ’16 gives us a tool to help solve this problem: the SandboxPostCopy interface.

The SandboxPostCopy interface

The SandboxPostCopy interface allows us to create an Apex class that can be executed automatically after a sandbox is refreshed. Here’s an example:

[code language=”javascript”]

global class OpFocusSandboxPostCopy implements SandboxPostCopy {

global void runApexClass(SandboxContext context) {

// Create the OpFocus Account

Account acctOpFocus = new Account(Name=’OpFocus, Inc.’);

acctOpFocus.BillingStreet = ’78 Blanchard Road, Suite 203′;

acctOpFocus.BillingCity    = ‘Burlington’;

acctOpFocus.BillingState  = ‘MA’;

acctOpFocus.BillingPostalCode = ‘01803’;

acctOpFocus.BillingCountry = ‘USA’;

insert acctOpFocus;




The runApexClass() method accepts one argument, a SandboxContext. Salesforce doesn’t provide much documentation about the SandboxContext class, but from the related documentation, we can tell that it supports at least the following methods:

  • organizationId()
  • sandboxName()

With our class defined and deployed to the OpFocus Production instance, whenever we refresh a sandbox, we can tell Salesforce to run our class:

Thus, whenever our sandboxes are refreshed, we can be sure that the reference data we need has been defined before we start to use the sandbox.

What about unit tests, you ask? Unit testing is pretty simple:

[code language=”javascript”]


static void testSandboxPostCopyScript() {

OpFocusSandboxPostCopy myPostSandboxCopy = new OpFocusSandboxPostCopy();

Test.testSandboxPostCopyScript(myPostSandboxCopy, null, null, null);

System.assertEquals(1, [select count() from Account]);



Again, Salesforce doesn’t provide documentation for the Test. testSandboxPostCopyScript(), but it takes the following arguments:

  • A reference to a class that implements the SandboxPostCopy interface
  • The org Id
  • The sandbox Id
  • The sandbox name

Although you must provide the first argument, the remaining arguments can be null, provided your SandboxPostCopy class doesn’t need their values.

No more excuses!

Now, with Spring ’16, you finally have a relatively easy way to create the reference data that your sandboxes need, which leaves you with no more excuses for not refreshing your sandboxes more often!

MJ Kahn, SVP of Technology at OpFocus

about the author

MJ Kahn

At OpFocus, MJ architects and constructs solutions that would impress the builders of the pyramids. She solves technical puzzles that would frustrate daVinci. She leaps tall buildings (like the new Salesforce tower) in a single bound.

Well ok, maybe she doesn’t. But she does help lead an amazing team of smart, talented, and dedicated consultants who do. MJ’s job at OpFocus is provide technical leadership and guidance to OpFocus clients and team members so that, working together, we can create innovative yet practical solutions to real-world business problems within the Salesforce ecosystem.

Prior to OpFocus, MJ built an extensive background in technology and has held a variety of development, consulting, and management positions at companies like Sybase, Vignette, and Honeywell, among others. In these roles, MJ’s focus was helping companies effectively and intelligently use technology to solve business problems. An Apex and Visualforce consultant since mid-2008, MJ has worked with scores of companies to help them understand and utilize platforms like to solve business issues and also guide them in developing their own AppExchange product offerings.