Adam Osiecki
written byAdam Osiecki
posted on November 7, 2022
Freelance Salesforce developer, passionate about delivering well-crafted solutions, always willing to walk an extra mile to get the job done. Working with Salesforce platform since 2017.

System.Assert Class vs System.assertEquals methods

In Winter '23 Release Salesforce introduced a new System.Assert class that contains new methods for asserting test conditions. In this post, I would like to take a closer look at the new class and see what is the difference between the 'new' and 'old' approaches.

Salesforce in release notes recommends that developers start using the new System.Assert as soon as possible and what is more to replace existing assertions. Let's see what are the arguments for doing that.

Separation of concerns

Ideally, the Class should have only one responsibility, let's take a quick look at the System class.
Until this release Salesforce provides three assert methods:

System.assert();
System.assertEquals();
System.assertNotEquals();

System class also contains a lot of different methods like scheduleBatch(), debug(), now(). They obviously have nothing in common with assertions. It looks like the System class is a God class. Removing methods from this class to new ones seems to be a good step.
Unfortunately, this is the only reason why I would say that I like the new Assert class, lets's see the next points to find out why:

ok-boomer

Multiple classes serving the same purposes

Does creating a new class for assertions mean that they are going to be removed from the original one? In this case obviously not. There are tons of orgs using the System.assert methods and it seems impossible to remove old methods from System class in foreseeable future. This way we have an even bigger mess because two different classes now have methods serving exactly the same purpose.

Less is better

This is only my private opinion, but I love the simplicity of the assertions in Apex. There are literally 3 methods to be remembered, and they are accepting multiple types of parameters which is super convenient to me. Right now we land with 2 separate classes and 12 methods in total. As a person who values my time and 'hard disk space (I'm trying to avoid saying lazy person 🙂 ), I need a solid justification to learn 9 new methods. This is why I checked method by method what are differences between old and new methods to see what benefits they bring:

New methods are just syntactic sugar

They are not bringing any new functionality, meaning that every new method could be replaced by the old assert method. See the table in table below, where I compared the new method and recommended the old equivalent.

Better communication when assertion fails?

New methods seem to provide more exact information about the reason why assertion fails (See the table below with my comments). For example when you are comparing the null value with the string 'null':

System.assertEquals(null, 'null', 'Your custom message here');

The output error might be a little bit confusing:

System.AssertException: Assertion Failed: Your custom message here: Expected: null, Actual: null

This was solved with the new method:

Assert.isNull('null');

Will give you following output:

System.AssertException: Assertion Failed: Nullable object asserted with non null value

So in this very specific case, this is less confusing. But what about the rest of the cases? In the old approach, you would see exactly what value was actually returned. In my opinion, this is very helpful when you glance through the test execution report. In most cases, you are able to immediately guess what is the reason for the tests failing. To provide this information in the new isNull method you would have to do the following:

Assert.isNull(actualValue, 'Actual value is: ' + actualValue);

This seems to be a good practice (I highly recommend adding a descriptive parameter in each assertion!), but we have to focus here on providing the actual value, not on the business-oriented description of what happens. I do prefer to provide some information that makes sense in the context of the test and assertion purpose, for example:

System.assertEquals(null, returnedAccounts, 'No accounts should be returned');

Which gives me more insights into what actually happened. When tests are failing on production deployment, every minute saved on the investigation counts. The conclusion is that the feature which is described by Salesforce as an improvement, for me actually it is a step backwards.

New Method Message when assertion fails Old equivalent Message when assertion fails Comment
Assert.areEqual(1, 2, 'Your custom message here'); System.AssertException: Assertion Failed: Your custom message here: Expected: 1, Actual: 2 System.assertEquals(1, 2, 'Your custom message here'); System.AssertException: Assertion Failed: Your custom message here: Expected: 1, Actual: 2 No difference between the old and new method
Assert.areNotEqual(1, 1, 'Your custom message here'); System.AssertException: Assertion Failed: Your custom message here: Same value: 1 System.assertNotEquals(1, 1, 'Your custom message here'); System.AssertException: Assertion Failed: Your custom message here: Same value: 1 No difference between the old and new method
Assert.fail('Your custom message here'); System.AssertException: Assertion Failed: Assertion failed: Your custom message here System.assert(false, 'Your custom message here'); System.AssertException: Assertion Failed: Your custom message here The old method has slightly cleaner communication when the assertion fails. On the other hand, using Assert.fail seems to better express the developer's intention when checking if the exception was thrown
Assert.isFalse(true, 'Your custom message here'); System.AssertException: Assertion Failed: Your custom message here Boolean truthy = true; System.assert(!truthy, 'Your custom message here'); System.AssertException: Assertion Failed: Your custom message here No difference between messages, the new method name seems to be a little bit cleaner than the old equivalent
Assert.isInstanceOfType(new Account(), Contact.class, 'Your custom message here'); System.AssertException: Assertion Failed: The provided object is not an instance of class Contact: Your custom message here Object o = new Account(); System.assert(o instanceof Contact, 'Your custom message here'); New class provides more detailed information out of the box when assertion fails The new class provides more detailed information when an assertion fails. This is the only assert method where actual value is a first result
Assert.isNotInstanceOfType(new Account(), Account.class, 'Your custom message here'); System.AssertException: Assertion Failed: The provided object is an instance of class Account: Your custom message here Object o = new Account(); System.assert(!(o instanceof Account), 'Your custom message here'); System.AssertException: Assertion Failed: Your custom message here The new class provides more detailed information when an assertion fails. This is the only assert method where actual value is a first result
Assert.isNotNull(null, 'Your message here'); System.AssertException: Assertion Failed: Instance expected to be a non null value: Your message here System.assertNotEquals(null, null, 'Your custom message here'); System.AssertException: Assertion Failed: Your custom message here: Same value: null The new class provides more detailed information when an assertion fails
Assert.isNull(new Account(), 'Your custom message here'); System.AssertException: Assertion Failed: Nullable object asserted with non null value: Your custom message here System.assertEquals(null, 'null', 'Your custom message here'); System.AssertException: Assertion Failed: Your custom message here: Expected: null, Actual: null The new class provides more detailed information when an assertion fails
Assert.isTrue(false, 'Your custom message here'); System.AssertException: Assertion Failed: Your custom message here System.assert(false, 'Your custom message here'); System.AssertException: Assertion Failed: Your custom message here No difference between the old and new method

Cleaner method names

Does Assert.fail('Your custom message here'); looks better than System.assert(false, 'Your custom message here');?

To me, yes. The method has fewer parameters which is always better. Does it mean that 1st option is so much better that I should replace all System.assert(false) in my code? I don't think so. I strongly disagree with the statement in the Release Notes saying that we should replace existing assert methods to use the new one. I'm ok with using new methods in newly created code, but on the other hand what about code consistency? When we should use the old one and when new one? I'm not saying that we should boycott new methods. My point is that choosing between old and new methods is a little bit more complex than saying "replace all existing System.assert methods with new ones and don't use old ones anymore". 
Another example of the method that looks nicer than the old ones is:

Assert.isInstanceOfType(new Account(), Contact.class, 'Your custom message here');

Which seems to be a nice way of comparing instance types. On the other hand, methods isInstanceOfType and isNotInstanceOfType are not consistent with the rest of the assertion methods. They are the only methods having actual result as a first parameter which might be a little bit confusing.

Summary

I'm not a big fan of the new Assert class.
If I had to choose whether I should use only new methods or keep the existing ones, I would prefer old ones. If I could mix them I would use Assert.fail and Assert.isInstanceOfType. I'm used to the simplicity of exising assertion methods - you can't teach an old dog new tricks
What is your opinion on this topic?

BTW. If you want to use new assert methods easily in VS Code, check our Salesforce Snippet Plugin here. We created snippets for all assert methods and much more


If you have some questions feel free to ask in the comment section below. 🙂

Was it helpful? Check out our other great posts here.


Resources

  1. New Assert class in Winter '23 Release Notes'
  2. Assert Class reference
  3. Salesforce Snippets by Beyond The Cloud
Buy Me A Coffee