function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Mario G.Mario G. 

Validation rules with $ Objects fields failing only in test methods

I have a trigger on a Lead that verifies if the lead has been converted and does some actions if some criteria is met.
The code seems to work fine on the application but my test class fails when I programatically convert a Lead.

The error seems to be a validation rule that fails.
This validation rule uses information from the $ objects provided:
$Setup.ypg_switches__c.data_Lead__c
Where ypg_switches is a hierarchical custom setting having data_Lead as a checkbox (true/false)
This "Error Condition Formula" always fails on my test method no matter what the value of the custom setting is with the following error:
16:32:39.116 (6116300765)|FATAL_ERROR|System.DmlException: Insert failed. First exception on row 0; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, Validation Formula "AC" Invalid (null): []
Usually we expect to receive the error message.

I also tested another Error Condition Formula:
$User.data_AllOrAccount__c
This is a calculated field on the user object that return true or false but i'm experiencing the same behaviour... failure nomatter what's the value.

My question are...
Is it possible that those $objects are not available when in test mode?
If not available, how to test something like this?  I don't want to disable any validation rules just to test code!
If available, what am I doing wrong?

Here's the whole test class:
/**************************************************************************
 * Tests the MigrateAssociatedAssignmentRequests fonction
 **************************************************************************/
@isTest static void MigrateAssociatedAssignmentRequestsTest() {
	Integer nbObjectsToTest = 1;
	
	//preparing test (creates the custom setting if not available)
	ypg_Switches sws = new ypg_Switches(false);
	sws.dataAllSwitch = true;
	sws.dataLeadSwitch = true;
	sws.dataLoadSwitch = false;
	sws.saveToSF();
	
	String ownerToUse = retrieveUserId('John Doe');
	String ARType = retreiveRType('Assignment_Request');
	
	Lead[] leads = generateTestLeads(nbObjectsToTest, '514');
	
	//create AR
	Case c = new Case(
		RecordTypeId = ARType,
		Type = AR_TYPE_GENERAL,
		Status = AR_STATUS_INPROGRESS,
		Requested_By__c = ownerToUse
	);
	
	insert c;
	
	list<Assignment_Request_Item__c> aris = new list<Assignment_Request_Item__c>();
	
	//create AR Item
	for(Lead l: leads) {
		Assignment_Request_Item__c ari = new Assignment_Request_Item__c(
			Lead__c = l.Id,
			Case__c = c.Id,
			Assignee__c = ownerToUse
		);
		
		aris.add(ari);
	}
	
	insert aris;
	
	//preparing Lead convert
	LeadStatus ls = [SELECT Id, MasterLabel FROM LeadStatus WHERE IsConverted=true LIMIT 1];
	list<Database.LeadConvert> converts = new list<Database.LeadConvert>();
	
	for(Assignment_Request_Item__c ari: aris) {
		Database.LeadConvert lc = new Database.LeadConvert();
		
		lc.setLeadId(ari.Lead__c);
		lc.setConvertedStatus(ls.MasterLabel);
		
		converts.add(lc);
	}
	
	Test.startTest();
	
	//convert leads
	Database.LeadConvertResult[] lcrs = Database.convertLead(converts);
	
	Test.stopTest();
	
	//asserting outcome
	system.assert(sws.dataAllSwitch);
	system.assert(sws.dataLeadSwitch);
	
	map<Id,Id> LeadToAcntMap = new map<Id,Id>();
	
	for(Database.LeadConvertResult lcr: lcrs) {
		system.assert(lcr.isSuccess());
		LeadToAcntMap.put(lcr.getLeadId(), lcr.getAccountId());
	}
	
	map<Id, Assignment_Request_Item__c> ariMap = new map<Id, Assignment_Request_Item__c>(aris);
	Assignment_Request_Item__c[] arisUpd = [SELECT Id, Case__c, Account__c, Lead__c FROM Assignment_Request_Item__c WHERE Id IN :ariMap.keySet()];
	
	for(Assignment_Request_Item__c ari: arisUpd) {
		system.assertEquals(null, ari.Lead__c);
		system.assertEquals(LeadToAcntMap.get(ariMap.get(ari.Id).Lead__c), ari.Account__c);
	}
}
Thanks for your help!



Best Answer chosen by Mario G.
bob_buzzardbob_buzzard
As document here:

http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_testing_data_access.htm

Custom settings (so $Setup values) are not available in test methods unless you use the @seeAllData=true annotation.

All Answers

bob_buzzardbob_buzzard
As document here:

http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_testing_data_access.htm

Custom settings (so $Setup values) are not available in test methods unless you use the @seeAllData=true annotation.
This was selected as the best answer
Mario G.Mario G.
That was it...  I forgot to read the fine prints...
Many thanks.
Sanchivan SivadasanSanchivan Sivadasan
Hey Guys,

I am having a similar issue. 

I have a Hierarchy Custom Setting. I have a validation rule that uses this Custom Setting to determine if the validation rule needs to be skipped. In my test class, I am setting the Custom Setting to be true so it should skip. But the validation is getting fired.

In the debug log, this is what I see:

System.DmlException: ConvertLead failed. First exception on row 0; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, Validation error on Account: Validation Formula "Restrict_Change_In_Account_Fields" Invalid (null): []

In the validation rule, this is what I have:

AND( 
NOT(ISNEW()), 
NOT($Setup.SkipValidation__c.SkipValidation__c), 
OR( 
ISCHANGED(OwnerId), 
ISCHANGED(Name) , 
ISCHANGED(ParentId) , 
ISCHANGED(BillingStreet), 
ISCHANGED(BillingCity) , 
ISCHANGED(BillingState) , 
ISCHANGED(BillingPostalCode)))

In the test class, I am not using seeAllData. I am actually creating the custom setting data and set it to true, but it ignores it. Any idea why? Thanks.

Sanchivan S.
Wiktoria AndruszkiewiczWiktoria Andruszkiewicz
5 years later I've got exactly the same issue as Sanchivan :( Does anyone have any idea what could be causing this and how to bypass the Validation Rule?