Print this page

Static objects in unit tests

Knowledge Article Number 000181523
Description Any time a database object is called in a static context, there is the possibility of row lock errors (UNABLE_TO_LOCK_ROW). If multiple tests need to access the same object -- or a group of similar objects -- then they may collide when making the call. Take, for example, the following calls that are issued from a number of different test locations:

Factory.setCustomProperties(false);
Factory.setCustomProperties(true);

These would reference the below method:

global static void setCustomProperties(Boolean auth){ 
Settings__c settings = Settings__c.getOrgDefaults(); 
settings.Authorization__c = auth; 
settings.Days__c = 1; 
upsert settings; 
}


 
Resolution To bypass row lock contention here, you'd need to actually treat this like a Singleton pattern, whereby only one call was issued to the static-level resource. That way, we're not instantiating a new duplicate object upon each call. 

private boolean calledAndSet = false;
global static void setCustomProperties(Boolean auth) {
if (!calledAndSet) {
Settings__c settings = Settings__c.getOrgDefaults();
settings.Authorization__c = auth;
settings.Days__c = 1;
upsert settings;
}
}

Here, we'd only issue one call to the logic -- upserting the settings only one time. You could actually break this down even further into methods per setting (e.g., setCustomPropertiesTrue, setCustomPropertiesFalse, etc.), allowing for a single call for each type of setting. This extends beyond just boolean logic. 

A singleton pattern would check to see if the sole object was actually null; if so, instantiate it and return it -- otherwise return the existing one. In the context of database calls, we're just ensuring that the object is inserted once and only once, since it's the same for all calls. 




promote demote