Why you should use System.Assert


assert-sign-photoshoppedOne of the many things I do to help further the awesomeness of Salesforce and to bring more developers on board is to review code – recommending best practices, coding styles, and just overall teaching good tips to write better code.

One of the many things that I end up talking about is why verification of your unit tests is important, not just raw line coverage. Writing APEX Unit Tests is a new concept for most developers coming in from other languages and platforms.  I know it was a new concept and honestly a bit of a struggle for me coming from .NET!

Let’s start by talking about one of the most common ways Salesforce developers get bit by the Unit Test ghost.  It’s not the initial development that gets you – it’s when you have to deploy new code six months down the road after your original code has been in the wild.  Taking an extra 10-15 minutes up front to systematically verify your test results will save you hours down the road, trust me. With very rare exception, there isn’t a single Salesforce org that remains completely static and rigid for a month, much less six months. Businesses are dynamic with new workflows, validation rules, APEX code, fields, (must I go on?) being added as processes are changed or refined.

As Murphy’s Law would have it, the first organizational change done will break your unit tests, and naturally you’ll only see it when you’re pushing code at 11pm on Friday night.

Bottom line:  The sooner we accept that the world is dynamic and our code will break, the sooner we can learn how to make our code intelligent enough to help us figure out why and how to fix it.

Salesforce has a great article on “Testing Examples” – I’m not going to rehash the nitty-gritty details in this blog, but I strongly urge you to go read it. The big three things that this article points out are:

  1. Test for your desired result (POSITIVE)
  2. Test for common errors (NEGATIVE)
  3. Test as the user(s) and profile(s) that will use this functionality

Why should you always cover these three areas in your unit tests?  Two words…”Business Rules”.  What you created wouldn’t need to exist if there weren’t business rules that drove the data to it.

Who does it, what are they doing, when do they do it, where do they do it, and why do they do it?

To build a true unit test, you need to answer these questions both positively and negatively, as well as within the context of the specific user(s) that are doing it. Now you’re saying, “Ok, I get it…how do I do it?” right? Enter System.Assert, System.AssertEquals, and System.AssertNotEquals!

The first mistake I made was only to test for positive results.  “It should work here, and my Assert will just tell me if it doesn’t, that’s cool right?”  Not completely – we want to make sure we test for both positive AND NEGATIVE outcomes, as your users will never follow the “happy path” you’ve coded consistently.

Ok, so here’s your rule of thumb.  If you are changing data through variable assignment, DML, or even just through normal code logic, you need to ensure that after everything is said and done what you EXPECT should have happened…DID.

Here are some examples – keep in mind these are VERY simplistic and meant only as demonstration aids.  Please refer to the Salesforce link above for full best practices!  (try/catch blocks, multiple assertions, full logic testing, etc., are all part of good Unit Tests!)

Example Positive:

Use Case – simple insertion of Account record

Account acctTest = new Account(Name='Test Account');
insert acctTest;
System.Assert(acctTest.Id != null, 'The Test Account did not insert properly, please check validation rules and other mechanisms');

Example Negative:

Use Case – existing Validation Rule that does not allow ‘Test’ in an Account Name

Account acctTest = new Account(Name='Test Account');
try {
insert acctTest;
} catch (Exception ex) {
System.Assert(ex.getMessage().contains('Insert Failed'), 'Account Validation Rule did not fire');
}

Example User Context:

Use Case – The ‘Service’ Profile need to be able to execute a DML “Update” of an Account record

Profile prfStandard = [select id from profile where name='Service']; 
 User uServiceUser = new User(alias = 'standt', email='standarduser@testyourorg.local', 
 emailencodingkey='UTF-8', lastname='Testing', languagelocalekey='en_US', 
 localesidkey='en_US', profileid = prfStandard.Id, timezonesidkey='America/Los_Angeles', username='standarduser@testyourorg.local');
Account acctTest = new Account(Name='Test Account');
insert acctTest;
System.runAs(uServiceUser) {

acctTest.Name = 'Test Account - Service Mod';
update acctTest;
System.Assert(acctTest.Name = 'Test Account - Service Mod','The Service Profile was not able to update an Account properly!');
}

TL;DR

At first, you’ll be really annoyed that “I have to do WHAT?!? C’mon, the logic is right there!”, and for your initial deployment that will be the case. Believe me six months down the road when new business logic has been introduced and you are deploying new code only to see your old code is failing…

You’ll be happy that you have Assertions in there to help guide you home quickly.  =)

Questions?  Comment away!

2 thoughts on “Why you should use System.Assert

  1. Hello Andrew,

    I have a test class written for my controller but missed few standards for test class.

    Can you please guide me

    @isTest(SeeAllData=true)
    public class custableTest
    {
    static testmethod void myTest()
    {

    Account a = new Account();
    a.Name=’CISCO’;
    insert a;
    Test.startTest();
    PageReference pageRef = Page.AccDet;
    pageRef.getParameters().put(‘id’, String.valueOf(a.Id));
    Test.setCurrentPage(pageRef);
    custable c = new custable();
    c.recid=’12345′;
    c.setupContacts();
    c.setupOpportunities();
    Test.stopTest();

    }

    }

Leave a comment