6

Is there a way to stop System.assert calls from executing throughout an org by a setting or programmatically?

I did not see anything in the Apex System class docs and the docs explicitly state that an assertion failure generates an exception that cannot be caught in a try/catch.

Right now, if I have code such as the following in my sandbox

public class MyController() {
    public MyController() {
        System.assert(false, 'Fail');
    }
}

it will result in the following being displayed when the VF page is rendered.

Assertion Failed: Fail

An unexpected error has occurred. Your development organization has been notified.

Java assert has had that capability. See Programming With Assertions - Enabling and Disabling Assertions, which is why I'm asking.

I know that it is debatable whether it is good practice or not to turn off assertions in production code, but I'm just interested in knowing how this can be done.

  • I've decided to throw my own exceptions (class InvalidDataException extends Exception) exactly because of this issue, Idon't want to display big scary blank page to the end users.. I think the meaning of the word is just different than in Java world ;) It's as if asserts would make sense only inside unit tests. – eyescream Oct 27 '12 at 21:54
7

Not that I can see either sadly...

Only thing I can recommend is wrapping some of the assert methods you use in a small framework like the one I've shown below. So that you then only call the System.assert methods in your tests methods, sandbox runtime or when explicitly configured otherwise.

To use the code below create a custom setting called Asserts with a field called Enabled in your production org (no need in sandbox, as its read dynamically). Once in production, you can then enable asserts at user, profile or org level, using the standard custom setting UI.

enter image description here

Then use this code instead of the System.assert methods..

Assert.equals('Night', 'Day', 'Its the difference between...');

Here is the code to dynamically check for your sandbox and custom settings.

public with sharing class Assert 
{   
    public static String MY_PRODUCTION_ORG_ID = '00ZX0000000CinBOBX';

    private static boolean Enabled = false;

    static
    {       
        // Enable for test and certain runtime contexts (such as sandbox)?
        Enabled = Test.isRunningTest() || UserInfo.getOrganizationId() != MY_PRODUCTION_ORG_ID; 
        if(!Enabled)
        {
            // Enabled via custom setting specified at user, profile or org level?
            Set<Id> locations = new Set<Id> 
                { UserInfo.getUserId(), UserInfo.getProfileId(), UserInfo.getOrganizationId() };
            try {
                List<SObject> enabledSettings = Database.query(
                    'select Id From Asserts__cX ' + 
                        'where SetupOwnerId in :locations and ' + 
                               'Enabled__c = true');    
                Enabled = enabledSettings.size() > 0 ? true : false;
            } catch (Exception e) { }   
        }           
    }   

    public static void equals(Object x, Object y, Object msg)
    {
        if(Enabled)
            System.assertEquals(x, y, msg);
    }
}

Assertion Failed: Its the difference between...: Expected: Night, Actual: Day

An unexpected error has occurred. Your development organization has been notified.

:-)

| improve this answer | |
  • I didn't realise you'd posted a similar solution, I wasn't plagiarising... honest :) It's great to read through some of your solutions Andy, real eye openers :) – techtrekker Oct 27 '12 at 10:55
  • Ah no worries, easy not to spot new answers being added, we are all so keen to help here! :-) Good fun and thanks for the compliment. I hope to be at your dizzy rep heights one day! – Andrew Fawcett Oct 27 '12 at 11:10
  • Would you not need SeeAllData=true to be able to query the Custom Setting, or am I missing something? – techtrekker Oct 27 '12 at 11:16
  • Actually to enabled asserts in a test context it does not need to, since you would want all your asserts enabled when running tests (i hope anyway!). If not, you could implement a Assert.init method to call in your test class method or static constructor to setup the custom settings how you want them. So I think... still no need for the icky SeeAllData=true? :-) – Andrew Fawcett Oct 27 '12 at 11:43
  • I guess, true you only need it for disabling in a Test Context. Just depends on the intent I reckon :) – techtrekker Oct 27 '12 at 11:45
2

I tried wrapping it in a try-catch and sure enough was presented with the same outcome you reported. Which makes me think, this will need something home grown, such as a Custom Setting (which would require SeeAllData=true, if the intent is to also disable asserts in a Test Context - if not CustomSettings are recommended), so maybe a Custom Label which controls the running of the Assertions, and you can switch it on and off from config.

//if Assertions are not Required to be Disabled in Tests, Use A Custom Setting instead
boolean assert= Boolean.valueOf(System.Label.Assert_Assertions);

if(assert)
System.assertNotEquals(null, email);

It doesn't sound too appetising to pepper tests with if statements; I wonder if an AssertionDelegate is the answer

public class AssertionDelegate{

static boolean assert = Boolean.valueOf(System.Label.Assert_Assertions);

public static void assertNotEquals(Object arg1, Object arg2){
if(assert)
System.assertNotEquals(arg1, arg2);
}
}

AssertionDelegate.assertNotEquals('abc', 'abc');
| improve this answer | |
  • Curious as to why use of Custom Setting would require SeeAllData=true? – Andrew Fawcett Oct 27 '12 at 10:06
  • Unless Im having a brain freeze, without setting SeeAllData = true, you wouldn't be able to see any data in the CustomSettings in the test that is running? Same as say an Account record? I'm sure I've seen that happen. (at least I think I have... :) ) – techtrekker Oct 27 '12 at 10:17
  • "Starting with Apex code saved using Salesforce.comAPI version 24.0 and later, test methods don’t have access by default to pre-existing data in the organization, such as standard objects, custom objects, and custom settings data, and can only access data that they create." Source : salesforce.com/us/developer/docs/apexcode/Content/… – techtrekker Oct 27 '12 at 10:21
  • Correct, I guess though it depends on how you view the custom setting. If its presence is to disable the asserts then you don't need any data present in the setting for the default behaviour. Then in production ensure that it is present to disable them. Alternatively you could have a static constructor in your tests to initialise your custom setting with data. I think this would work, no? – Andrew Fawcett Oct 27 '12 at 10:21
  • My objective was to not have a compile time dependency. Hence the approach. – techtrekker Oct 27 '12 at 10:22

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.