0

I have written a test for a trigger handler that accesses a custom setting like so:

Integer dueDateA = (Integer) (Dealer_Class_Due_Date__c.getValues('A').Days_to_Add__c); (in Trigger Handler)

However, my test class throws an error at that line saying it is null. I added @isTest(SeeAllData=true) in my method signature and it worked fine, but it is causing issues with something else I am trying to do and was wondering if there was an alternative?

6
  • Is there a reason you are not creating an instance of Dealer_Class_Due_Date__c in your test class instead? I would recommend this approach as you are decoupling top level data from your many test scenarios.
    – TSmith
    Jul 16 at 12:36
  • How can I use it after I create the instance? I don't have a constructor or anything I would pass it through.
    – Carly
    Jul 16 at 12:37
  • Either in your test method or test setup, Dealer_Class_Due_Date__c setting = new Dealer_Class_Due_Date__c(FieldA = 'Hello', FieldB = true); where you define the field values for testing.
    – TSmith
    Jul 16 at 12:38
  • How can I reference the field names in this approach? I tried A and A__c but both says the field does not exist.
    – Carly
    Jul 16 at 12:41
  • So I tried Dealer_Class_Due_Date__c setting = new Dealer_Class_Due_Date__c(Days_to_Add__c = 30); but I want the records of the Days_toAdd__c rather than the field itself, which are A, B, C that store integers. how can I do this?
    – Carly
    Jul 16 at 12:45
1

Custom setting data is data (as opposed to being metadata). That means that you need to explicitly create data for them in tests, just as you would for an Account, Contact, or Opportunity.

If you were to use a Custom Metadata Type (which is suggested as a replacement for list-type custom settings), then you wouldn't need to explicitly add records for it in your test (custom metadata types are metadata). Custom Metatada Type records in a given org are visible in unit tests with the default mode (seeAllData=false).

1

As @DerekF said in his answer, custom settings are data and so need to be created in the context of unit tests.

However, what Derek didn't mention is that if you do this, and actually commit custom settings instances to the database, you will run into database locking problems if you run unit tests in parallel where the same instances are created in the database by different unit tests. This happens even though Salesforce is supposed to provide isolated databases to each separate unit test. While the data itself is only visible in a given unit test, there is still contention in the over-all database during such conflicting instance creations.

I recommend, therefore, that you either:

  1. follow Derek's suggestion and switch to Custom Metadata Type instances; the downside here is that your unit tests become dependent on external data unless you provide a separate mechanism in your unit testing to mock out these instances OR
  2. refactor your application logic to use a single source of custom settings instances - e.g. a Settings class with methods to access your various types of custom settings. This class can be written to locally cache the custom settings instances returned to the code, which allows your unit tests to fetch the instance first, set the required values in the settings fields, and then rely on the production code under test to retrieve this same cached instance through this class and therefore see the correct settings for the test, all without ever saving the instance to the database.

Either way, you have some infrastructure/plumbing code to add to let you do this cleanly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.