Pages

June 17, 2019

Salesfore Apex Test Class Best Pracitces

Apex Unit Tests

The Apex testing framework enables you to write and
execute tests for your Apex classes and triggers on the Lightning Platform.
Apex unit tests ensure high quality for your Apex code and let you meet
requirements for deploying Apex.

Salesforce recommends that you write tests for the
following:

Single action

Test to verify that a single record produces the correct,
expected result.

Bulk actions

Any Apex code, whether a trigger, a class or an
extension, may be invoked for 1 to 200 records. You must test not only the
single record case, but the bulk cases as well.

Positive behavior

Test to verify that the expected behavior occurs through
every expected permutation, that is, that the user filled out everything
correctly and did not go past the limits.

Negative behavior

There are likely limits to your applications, such as not
being able to add a future date, not being able to specify a negative amount,
and so on. You must test for the negative case and verify that the error
messages are correctly produced as well as for the positive, within the limits
cases.

Restricted user

Test whether a user with restricted access to the
sObjects used in your code sees the expected behavior. That is, whether they
can run the code or receive error messages.

The code inside Test.startTest() and Test.stopTest() have
new set of Salesforce Governor Limits. As a good practice, make sure
initializing the variables, fetching records, creating and updating records are
coded before Test.startTest() and Test.stopTest() and calling the controllers
for code coverage is done inside Test.startTest() and Test.stopTest(). The code
before Test.startTest() and after Test.stopTest() have new set of Salesforce
Governor Limits and code between Test.startTest() and Test.stopTest() have new
set of Salesforce Governor Limits.

Any code that executes after the stopTest method is
assigned to the original limits that were in effect before startTest was
called.

4. System.assert, System.assertEquals
and System.assertNotEquals

System.Assert accepts two parameters, one (mandatory) which
is the condition to test for and the other a message (optional) to display
should that condition be false.

System.AssertEquals and System.AssertNotEquals both
accepts three parameters; the first two (mandatory) are the variables that will
be tested for in/equality and the third (optional) is the message to display if
the assert results in false.

Both are used in Test Class for “Positive Case Testing”
and “Negative Case Testing” with single and multiple records.

Sample Code:

Trigger:

1.trigger AccountTrigger on Account ( before insert ) {

2.

3.for ( Account acct : trigger.new ) {

4.

5.if ( acct.Name == 'Test Account' )

6. acct.Description = 'Test';

7.

8. }

9.

10.}

Test Class:

1.@isTest

2.privateclass SampleTestClass {

3.

4.static testMethod void insertAcctTest() {

5.

6. Account acc = new Account(Name = 'Test Account');

7. insert acc;

8. acc = [ SELECT Description FROM Account WHERE Id = : acc.Id ];

9. System.assertEquals('Test', acc.Description);

10.

11. }

12.

13.}

In the above example, the expected Description of the
Account is 'Test'. If any other additional processes like Workflow Field
update, Process Builder, etc updates the Description other than 'Test', it will
throw an error and fails the test method. This will make sure that developed
code is working as expected.

Opposite to System.assertEquals() is
System.assertNotEquals().

5. runAs Method

Use the runAs method to test your application in
different user contexts.

The system method runAs enables you to write test methods
that change either the user contexts to an existing user or a new user. When
running as a user, all of that user's record sharing is then enforced. You can
only use runAs in a test method. The original system context is started again
after all runAs test methods complete.

The following items use the permissions granted by the
user specified with runAs running as a specific user:

Dynamic Apex

Classes using with sharing or without sharing

Shared records

The original permissions are reset after runAs completes.

The runAs method ignores user license limits. You can
create new users with runAs even if your organization has no additional user
licenses.

In the following example, a new test user is created, then
code is run as that user, with that user's record sharing access:

12. Adding SOSL Queries to Unit Tests
To ensure that test methods always behave in a predictable way, any Salesforce Object Search Language (SOSL) query that is added to an Apex test method returns an empty set of search results when the test method executes. If you do not want the query to return an empty list of results, you can use the Test.setFixedSearchResults system method to define a list of record IDs that are returned by the search. All SOSL queries that take place later in the test method return the list of record IDs that were specified by the Test.setFixedSearchResults method. Additionally, the test method can call Test.setFixedSearchResults multiple times to define different result sets for different SOSL queries. If you do not call the Test.setFixedSearchResults method in a test method, or if you call this method without specifying a list of record IDs, any SOSL queries that take place later in the test method return an empty list of results.

The list of record IDs specified by the Test.setFixedSearchResults method replaces the results that would normally be returned by the SOSL query if it were not subject to any WHERE or LIMIT clauses. If these clauses exist in the SOSL query, they are applied to the list of fixed search results.

Note:
1. Although the record may not match the query string in the FIND clause, the record is passed into the RETURNING clause of the SOSL statement.
2. If the record matches the WHERE clause filter, the record is returned. If it does not match the WHERE clause, no record is returned.