How to Write Test Classes in Salesforce - Solution for Guru

Table of Contents
< All Topics
Print

How to Write Test Classes in Salesforce

📝 Summary

This article provides a comprehensive guide to writing test classes in Salesforce. Test classes ensure that your Apex code works as expected and meets Salesforce’s deployment requirements by achieving at least 75% code coverage.


⚙️ What Are Test Classes?

Test classes are written in Apex to verify that your triggers, classes, and other logic behave as expected. They simulate real-world scenarios without affecting actual data.


✅ Benefits of Writing Tests

  • Required for deployment to production.
  • Help catch bugs early.
  • Validate business logic under various conditions.
  • Ensure future code changes don’t break existing functionality (regression testing).

📌 Key Requirements

  • Minimum 75% code coverage for deployment.
  • All triggers must be tested.
  • Positive and negative test cases should be included.
  • Use System.assert() statements to validate behavior.

🛠 Basic Structure of a Test Class

@isTest
private class AccountHandlerTest {

@testSetup
static void setupData() {
    Account acc = new Account(Name = 'Test Account');
    insert acc;
}

@isTest
static void testAccountInsertLogic() {
    Contact con = new Contact(FirstName = 'Test', LastName = 'User', AccountId = [SELECT Id FROM Account LIMIT 1].Id);
    insert con;

    // Validate behavior
    Contact insertedCon = [SELECT Description FROM Contact WHERE Id = :con.Id];
    System.assertEquals('Created by trigger', insertedCon.Description);
}

}

🔑 Best Practices

1. Use @isTest Annotation

  • Marks the class or method as a test.
  • Test classes do not count against org Apex limits.

2. Use @testSetup for Common Data

  • Creates baseline data that is reused across tests.
  • Runs once per test class, improving performance.

3. Test All Logic Paths

  • Positive tests (valid inputs).
  • Negative tests (invalid inputs, exceptions).
  • Edge cases (empty fields, null values).

4. Avoid Using SeeAllData=true

  • Tests should be isolated from org data.
  • Create all necessary test data programmatically.

5. Use System.assert()

  • Validates that actual results match expectations.

6. Cover Bulk Operations

  • Simulate inserts/updates with up to 200 records.

7. Test Triggers and Exceptions

  • Make sure you cover both success and failure paths.

💡 Common Patterns

Positive Test

@isTest
static void testValidInsert() {
Account acc = new Account(Name = ‘Test’);
insert acc;
System.assertNotEquals(null, acc.Id);
}

Negative Test (Expecting Failure)

@isTest
static void testInvalidInsert() {
try {
Account acc = new Account(); // Missing required Name
insert acc;
System.assert(false, ‘Insert should have failed’);
} catch (DmlException e) {
System.assert(e.getMessage().contains(‘Name’));
}
}

📊 Viewing Code Coverage

  • Setup > Apex Test Execution
  • Developer Console > Test > New Run
  • Use Test.run() in Anonymous Apex to run test methods programmatically.

❌ Common Mistakes

MistakeImpactFix
Not creating test dataTests fail or behave unpredictablyUse @testSetup or method-level test data
Not using System.assert()Tests don’t verify logicAlways assert expected results
Overusing SeeAllData=trueMakes tests dependent on real dataCreate all required test data in the test class
Ignoring exceptionsCan miss logic flawsInclude tests for invalid inputs and error conditions
Only testing one recordDoesn’t cover bulk behaviorSimulate large data sets (up to 200 records)

🧪 Example: Testing a Trigger

@isTest
private class ContactTriggerTest {

@isTest
static void testBeforeInsert() {
    Contact c = new Contact(FirstName='John', LastName='Doe');
    insert c;

    Contact inserted = [SELECT Description FROM Contact WHERE Id = :c.Id];
    System.assertEquals('Created by trigger', inserted.Description);
}

}