Test.startTest() and Test.stopTest()

5 minutes 5 Questions

Test.startTest() and Test.stopTest() are critical methods in Apex testing that define a controlled execution context within a test method. Together, they establish a fresh set of governor limits, allowing developers to accurately test their code without being impacted by the setup operations performed before the test logic begins. **Test.startTest():** This method marks the beginning of the actual test execution phase. Any code written before this call is typically used for setting up test data (e.g., inserting records, creating objects). Once Test.startTest() is called, Salesforce resets the governor limits, giving the code between startTest() and stopTest() its own independent set of limits. This ensures that data setup operations do not consume limits that would otherwise be needed for the code under test. **Test.stopTest():** This method marks the end of the test execution phase. It signals Salesforce to enforce the governor limits collected between startTest() and stopTest(). Importantly, Test.stopTest() also forces any asynchronous operations (such as @future methods, Queueable jobs, Batch Apex, and scheduled Apex) that were invoked between startTest() and stopTest() to execute synchronously. This allows developers to verify the results of asynchronous code immediately after stopTest() is called. **Key Benefits:** 1. **Governor Limit Isolation:** Setup code and actual test logic have separate governor limit contexts, enabling more accurate limit testing. 2. **Asynchronous Testing:** Asynchronous processes are forced to complete synchronously, making it possible to assert their outcomes within the same test method. 3. **Best Practice:** Using these methods is considered a Salesforce best practice for writing robust, reliable test classes. **Usage Example:** Test data is inserted before Test.startTest(). The method or trigger being tested is invoked between startTest() and stopTest(). Assertions are placed after stopTest() to validate expected outcomes. Note: Each test method can only call Test.startTest() and Test.stopTest() once. They must always be used as a pair within the same test method.

Test.startTest() and Test.stopTest() in Salesforce – A Complete Guide

Why Is This Topic Important?

Understanding Test.startTest() and Test.stopTest() is essential for every Salesforce Platform Developer I candidate. These two methods are foundational to writing effective, governor-limit-aware unit tests. They appear frequently on the certification exam, and mastering them demonstrates your ability to write robust Apex tests that properly isolate the code under test from the test setup logic. Without a solid grasp of these methods, you risk losing easy points on exam questions related to testing, debugging, and deployment.

What Are Test.startTest() and Test.stopTest()?

Test.startTest() is a method that marks the point in your test method where the actual testing begins. Everything before this call is considered test setup (creating records, preparing data, etc.). Once Test.startTest() is called, Salesforce resets the governor limits, giving your code under test a fresh set of governor limits.

Test.stopTest() marks the end of the test execution context. When this method is called, Salesforce enforces the completion of all asynchronous operations (such as @future methods, Queueable jobs, Batch Apex, and Scheduled Apex) that were initiated between Test.startTest() and Test.stopTest(). This makes asynchronous code testable in a synchronous manner.

How Do They Work?

Here is the general pattern:

1. Setup Phase – Insert test data, create records, and perform any prerequisite configuration. This code runs under its own set of governor limits.

2. Test.startTest() – Call this method. At this point, Salesforce resets all governor limit counters (SOQL queries, DML statements, CPU time, etc.) to zero. Your code under test now gets a completely fresh set of limits.

3. Execution Phase – Execute the code you want to test. This could be a trigger, a method call, a web service callout (with a mock), or initiating an asynchronous process.

4. Test.stopTest() – Call this method. Salesforce forces all asynchronous processes that were enqueued between startTest and stopTest to complete immediately and synchronously. Governor limits are also evaluated at this point for the code that ran between the two calls.

5. Assertion Phase – After stopTest(), query the database and use System.assert(), System.assertEquals(), or System.assertNotEquals() to verify the expected outcomes.

Example Structure:

@isTest
static void testAccountTrigger() {
    // Setup phase – this does NOT count against the code-under-test limits
    Account acc = new Account(Name = 'Test Account');
    insert acc;

    // Reset governor limits
    Test.startTest();

    // Code under test
    acc.Name = 'Updated Account';
    update acc;

    // Force async completion and evaluate limits
    Test.stopTest();

    // Assertions
    Account result = [SELECT Name FROM Account WHERE Id = :acc.Id];
    System.assertEquals('Updated Account', result.Name);
}

Key Behaviors to Remember:

• Governor Limit Reset: The primary purpose of Test.startTest() is to provide a fresh set of governor limits so that data setup operations do not interfere with the limits available to the code being tested.

• Asynchronous Execution: Test.stopTest() forces all asynchronous operations (future methods, queueable, batch, scheduled) to execute synchronously. This means you can write assertions after Test.stopTest() and be confident that the async work has completed.

• One Pair Per Test Method: You can only call Test.startTest() and Test.stopTest() once per test method. Calling them more than once will result in a runtime error.

• Mixed DML Workaround: Test.startTest() and Test.stopTest() can help manage mixed DML errors in tests. Setup objects (like User) inserted before Test.startTest() exist in a different execution context than standard object DML inside the startTest/stopTest block, which can help avoid mixed DML exceptions in certain patterns (though using System.runAs() is the more common solution).

• Callout Mocks: When testing HTTP callouts, you set up the mock (Test.setMock()) before Test.startTest(), then invoke the callout logic between startTest and stopTest.

Common Misconceptions:

• Test.startTest() does not create a separate transaction. It simply resets the governor limit counters.
• Test.stopTest() does not roll back DML. All data changes persist within the test context (and are rolled back only at the very end of the entire test method, as all test data is automatically rolled back).
• Test.startTest() and Test.stopTest() are not required for a test to run or for code coverage. They are best practices for proper limit isolation and async testing, but test methods compile and run without them.

When to Use Them:

• When you need to ensure your code under test has its own governor limit allocation separate from your test setup.
• When testing asynchronous Apex (future, queueable, batch, scheduled) – Test.stopTest() is the only way to force these to run synchronously in a test context.
• When testing large-volume data operations where setup consumes significant governor limits.
• When testing callouts with mock responses.

Exam Tips: Answering Questions on Test.startTest() and Test.stopTest()

1. Look for governor limit questions: If an exam question asks how to ensure that test data setup does not consume the governor limits available to the code under test, the answer is Test.startTest().

2. Async testing questions: If a question asks how to test a @future method, a Queueable job, or a Batch Apex class, the correct approach involves calling the async code between Test.startTest() and Test.stopTest(). The assertions should come after Test.stopTest().

3. Remember the one-pair rule: If an answer option suggests calling Test.startTest() multiple times in the same test method, that option is incorrect.

4. Placement matters: On the exam, pay close attention to where Test.startTest() and Test.stopTest() are placed in code snippets. Setup should be before startTest(), the code under test between startTest() and stopTest(), and assertions after stopTest().

5. Assertions after stopTest(): If a question shows assertions placed between startTest() and stopTest() for async code, that pattern is problematic because the async code may not have completed yet. Correct placement is after stopTest().

6. Do not confuse with Test.isRunningTest(): Test.isRunningTest() is a different method entirely – it returns a Boolean indicating whether the code is being executed in a test context. Do not mix it up with startTest/stopTest.

7. Batch Apex specifics: When testing batch Apex, you call Database.executeBatch() between Test.startTest() and Test.stopTest(). The stopTest() call forces the batch to execute (start, execute, and finish methods all run). Query results and assertions should be placed after stopTest().

8. Elimination strategy: On tricky questions, eliminate answers that suggest alternatives like Thread.sleep(), manual delays, or multiple startTest() calls. These are common distractors.

9. Code coverage misconception: Some questions may try to imply that Test.startTest() is required for code coverage. It is not required for coverage – it is a best practice for limit management and async testing. Code between the two calls and outside of them both counts toward coverage.

10. Combine with System.runAs(): Some questions may combine Test.startTest()/stopTest() with System.runAs() to test code running as a specific user. These are complementary patterns and can absolutely be used together in the same test method.

By understanding these concepts thoroughly, you will be well-prepared to handle any exam question related to Test.startTest() and Test.stopTest() with confidence.
Test mode:

PD1 - Test.startTest() and Test.stopTest() Example Questions

Test your knowledge of Test.startTest() and Test.stopTest()

Question 1

A new developer is writing their first Apex test. They create a test method that inserts 3 Account records and then calls a custom method that queries those Accounts. The developer asks: 'Where should I place Test.startTest() and Test.stopTest() in my test?' What is the correct guidance?

Question 2

In Apex test methods, what is the maximum number of pairs of Test.startTest() and Test.stopTest() that can be invoked within a single test method?

Question 3

A new developer is writing their first Apex test method. They insert 3 Account records, call Test.startTest(), invoke a method that updates those Accounts, then call Test.stopTest(), and finally add assertions. The developer asks: 'What is the main reason we wrap the method call between Test.startTest() and Test.stopTest()?'

More Test.startTest() and Test.stopTest() questions
46 questions (total)