Apex Test Class

Apex Test Class Practice Problems

12 free Salesforce Apex challenges · Full problem statements, best-practice notes, and step-by-step hints · Solve live on ApexArena

This guide walks through 12 writing @isTest classes with proper test data, assertions, and bulk/negative-path coverage. Each entry below includes the full problem statement, the governor-limit and best-practice constraints it's testing, and a numbered approach to solving it — then you can open the same problem in ApexArena's browser-based Apex editor and get instant pass/fail feedback against real test cases.

On this page
  1. 1. Test Data Factory Pattern
  2. 2. Apex Test Class Best Practices
  3. 3. Write Test Class for Account Rating Trigger
  4. 4. Test Class for Contact Duplicate Trigger
  5. 5. Test Class for Opportunity Helper
  6. 6. Test Bulk Operations with Governor Limits
  7. 7. Test Class for Account Service
  8. 8. Mock HTTP Callout in Test Class
  9. 9. Test Class for Batch Apex
  10. 10. Test Class: Write Tests for Account Rating Trigger
  11. 11. Test Class: Write Tests for Duplicate Email Guard Trigger
  12. 12. Test Class: Write Tests for Case SLA Escalation Handler
Easy Test

1. Test Data Factory Pattern

Problem #6 · Salesforce Apex Coding Challenge

Problem Statement

Create a TestDataFactory class with static methods to generate realistic test data for Account, Contact, and Opportunity records. Support both insert and no-insert modes.

Requirements

  • Use a counter so names are unique per test run
  • createContact must accept an Account parameter
  • createOpportunity must have valid StageName and CloseDate
Approach
  • 1For Contact: set FirstName, LastName, Email, and AccountId = acc.Id.
  • 2For Opportunity: StageName = 'Prospecting', CloseDate = Date.today().addDays(30).
  • 3The static counter ensures unique names even when multiple records are created.
Medium Test

2. Apex Test Class Best Practices

Problem #19 · Salesforce Apex Coding Challenge

Problem Statement

Write a complete @isTest class for the AccountRatingTrigger (Problem 1). The test class must follow all Apex testing best practices.

Requirements

  • Use @TestSetup to create shared test data
  • Positive test: verify Rating = 'Hot' for revenue > 1M
  • Negative test: verify Rating = 'Cold' for revenue < 100K
  • Bulk test: insert 200 records and assert all are rated
  • Use System.assertEquals() for assertions (not just assert)
Approach
  • 1In @TestSetup: insert Account records using Test.loadData() or manual insert with a list.
  • 2Query after insert to get the trigger-modified values: Account a = [SELECT Rating FROM Account WHERE Id = :acc.Id]
  • 3For bulk test: use a for loop to build a List of 200 Accounts, then insert the list.
Easy Test Class

3. Write Test Class for Account Rating Trigger

Problem #24 · Salesforce Apex Coding Challenge

Problem Statement

Write a test class AccountRatingTriggerTest with at least 3 test methods covering the Account Rating trigger:

  • Revenue > 1,000,000 → Rating = Hot
  • Revenue 100,000–1,000,000 → Rating = Warm
  • Revenue < 100,000 → Rating = Cold

Requirements

  • Use @isTest annotation on the class and each method
  • Use Test.startTest() / Test.stopTest()
  • Use System.assertEquals() for assertions
Approach
  • 1Create an Account, insert it inside Test.startTest()/stopTest(), then query it back and assert.
  • 2System.assertEquals(expected, actual, 'message') is the standard assertion.
Medium Test Class

4. Test Class for Contact Duplicate Trigger

Problem #27 · Salesforce Apex Coding Challenge

Problem Statement

Write a test class ContactDuplicateTest that tests the Contact duplicate-prevention trigger:

  • Positive test: inserting a contact with a unique email succeeds
  • Negative test: inserting a contact with a duplicate email throws a DmlException

Requirements

  • Use try/catch with DmlException in the negative test
  • Assert the exception message contains "Email"
  • Achieve 100% code coverage of the trigger
Approach
  • 1Use try { insert dup; System.assert(false, 'Should have thrown'); } catch (DmlException e) { System.assert(e.getMessage().contains('Email')); }
  • 2The @isTest annotation on the class and methods is required.
Easy Test Class

5. Test Class for Opportunity Helper

Problem #31 · Salesforce Apex Coding Challenge

Problem Statement

Write a test class OpportunityHelperTest that achieves 100% coverage of OpportunityHelper.isWon() and isLost().

Include test methods for:

  • "Closed Won" → isWon = true
  • "Closed Lost" → isLost = true
  • Any other stage → both return false
  • Null input → returns false (no NPE)
Approach
  • 1Test null: System.assertEquals(false, OpportunityHelper.isWon(null));
  • 2Test case: System.assertEquals(true, OpportunityHelper.isWon('CLOSED WON'));
Hard Test ClassGovernor

6. Test Bulk Operations with Governor Limits

Problem #35 · Salesforce Apex Coding Challenge

Problem Statement

Write a test class BulkTriggerTest that validates that a trigger on Account handles 200 records in a single DML without hitting governor limits.

Requirements:

  • Insert 200 Account records in a single insert call
  • Assert all 200 were created (query count)
  • Assert Limits.getQueries() ≤ 5 (low SOQL usage)
  • Assert Limits.getDmlStatements() ≤ 3
Approach
  • 1Integer count = [SELECT COUNT() FROM Account WHERE Name LIKE 'Test Account%'];
  • 2Limits.getQueries() returns the number of SOQL queries used in this transaction.
Medium Test ClassSOQL

7. Test Class for Account Service

Problem #39 · Salesforce Apex Coding Challenge

Problem Statement

Write a test class AccountServiceTest for AccountService:

  • Set up test data using @testSetup
  • Test getHotAccounts() returns only accounts with Rating = 'Hot'
  • Test deactivateSmallAccounts() updates the right records
Approach
  • 1@testSetup runs once and data persists for all test methods in the class.
  • 2System.assertEquals(expectedSize, actualList.size(), 'message');
Hard Test Class

8. Mock HTTP Callout in Test Class

Problem #42 · Salesforce Apex Coding Challenge

Problem Statement

Write a test class HttpCalloutServiceTest that mocks an HTTP callout using HttpCalloutMock.

Steps:

  1. Create an inner class implementing HttpCalloutMock
  2. Set the mock with Test.setMock()
  3. Call HttpCalloutService.callWithRetry() and assert the response
Approach
  • 1String result = HttpCalloutService.callWithRetry('https://example.com', 3);
  • 2System.assertEquals('{"status":"ok"}', result);
Hard Test ClassBatch

9. Test Class for Batch Apex

Problem #46 · Salesforce Apex Coding Challenge

Problem Statement

Write a test class DeactivateOldContactsBatchTest:

  • Create 5 Contacts with LastActivityDate 400 days ago
  • Execute the batch using Database.executeBatch()
  • Assert all 5 have Active__c = false after batch runs
Approach
  • 1Test.startTest(); Database.executeBatch(new DeactivateOldContactsBatch(), 200); Test.stopTest();
  • 2After stopTest(), the batch finishes synchronously in test context.
Easy TestTriggers

10. Test Class: Write Tests for Account Rating Trigger

Problem #161 · Salesforce Apex Coding Challenge

Problem Statement

A trigger + handler already exist that set Account.Rating based on AnnualRevenue (Hot > 1M, Warm 100K–1M, Cold < 100K). Your task is to write a complete test class.

Required Test Methods

  • TC01 — Revenue > 1M → Rating = 'Hot'
  • TC02 — Revenue 500K → Rating = 'Warm'
  • TC03 — Revenue 50K → Rating = 'Cold'
  • TC04 — Null Revenue → no exception (graceful)
  • TC05 — Bulk insert 200 records → no governor errors
  • TC06 — Update Revenue 50K → 2M → Rating changes to Hot

Best Practices

  • @isTest on every test method.
  • Test.startTest() / Test.stopTest() wrapping DML.
  • Re-query the record after DML before asserting.
  • System.assertEquals for all assertions.
Approach
  • 1Re-query after insert: acc = [SELECT Rating FROM Account WHERE Id = :acc.Id]
  • 2For bulk: insert 200 accounts, then query and spot-check.
  • 3For update test: insert with 50K (Cold), update AnnualRevenue to 2M, assert Hot.
  • 4Wrap all DML in Test.startTest() / Test.stopTest() to reset governor limits.
Medium TestTriggersValidation

11. Test Class: Write Tests for Duplicate Email Guard Trigger

Problem #162 · Salesforce Apex Coding Challenge

Problem Statement

A trigger + handler prevent two Contacts sharing the same Email. Write a comprehensive test class covering all scenarios below.

Required Scenarios

  • Positive — Unique email inserts successfully.
  • Negative — Duplicate email throws DmlException with "already exists".
  • Case-insensitiveUPPER@test.com blocks upper@test.com.
  • Self-update — Updating own record without changing email passes.
  • Bulk unique — 50 contacts with unique emails all insert.
  • Bulk duplicate — 49 unique + 1 duplicate → only duplicate blocked.
Approach
  • 1Use try/catch(DmlException e) for negative tests.
  • 2Case-insensitive: insert "UPPER@test.com", then try "upper@test.com" → expect DmlException.
  • 3Self-update: insert, change FirstName only, update — no error expected.
  • 4Bulk duplicate: use Database.insert(list, false) and check SaveResult[] for the one failure.
Hard TestTriggersValidation

12. Test Class: Write Tests for Case SLA Escalation Handler

Problem #163 · Salesforce Apex Coding Challenge

Problem Statement

A handler exists that on before update of a Case:

  • Status → 'Escalated' (new): sets Priority = 'High' and Escalation_Reason__c = 'SLA Breach — auto-escalated'.
  • Status was already 'Escalated': calls addError('Case is already escalated.').

Write a full test class covering all six scenarios:

  • Valid escalation → Priority = High, reason contains "SLA".
  • Double escalation → DmlException with "already escalated".
  • Non-escalated status change → Priority unchanged.
  • Bulk 50 valid escalations → all Priority = High.
  • Bulk mixed (25 new + 25 already escalated) → 25 errors using Database.update(false).
  • Escalation_Reason__c content assertion → contains "SLA".
Approach
  • 1Double escalation: insert Case with Status='Escalated', then update same record → addError fires.
  • 2Bulk mixed: insert 50 cases; first 25 Status='New', last 25 Status='Escalated'.
  • 3Set all 50 to Status='Escalated', use Database.update(cases, false), check SaveResult[].
  • 4Assert saveResults[i].isSuccess() for i < 25 and !saveResults[i].isSuccess() for i >= 25.

Practice All 12 Problems Free

Write and run real Apex code right in your browser — instant pass/fail feedback, best-practice linting, and governor limit monitoring. No Salesforce org needed.

Create Free Account → Explore All Problems
More Practice Topics
About ApexArena

ApexArena is a free, browser-based Salesforce Apex coding practice platform covering every major topic tested on the Salesforce Platform Developer I (PD1) and Platform Developer II (PD2) certification exams. All problems run directly in your browser with instant pass/fail feedback, best-practice linting (SOQL in loops, DML in loops, empty catch blocks), and governor limit monitoring — no Salesforce Developer Edition org required.

Related tutorials: Apex Triggers · SOQL · Batch Apex · Interview Q&A · Governor Limits