{"id":1572,"date":"2026-09-08T13:00:00","date_gmt":"2026-09-08T07:30:00","guid":{"rendered":"https:\/\/swapnilzambare.com\/blog\/testing-async-apex-starttest-stoptest\/"},"modified":"2026-09-08T13:00:00","modified_gmt":"2026-09-08T07:30:00","slug":"testing-async-apex-starttest-stoptest","status":"publish","type":"post","link":"https:\/\/swapnilzambare.com\/blog\/testing-async-apex-starttest-stoptest\/","title":{"rendered":"Testing Async Apex with Test.startTest and Test.stopTest"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Testing Async Apex means proving that code which runs later, such as Queueable jobs, Batch Apex, future methods and scheduled jobs, really does its work. In a normal test, those jobs would not run before your asserts. Test.startTest and Test.stopTest solve this by running all queued async work at a point you control.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In this post, you will learn what startTest and stopTest do, how they reset governor limits, and how to test Queueable and Batch jobs step by step. Async Apex itself gets full posts in Level 7, so here we keep the job code small. This builds on <a href=\"https:\/\/swapnilzambare.com\/blog\/testing-apex-triggers-bulk-negative\/\">testing Apex triggers<\/a>, <a href=\"https:\/\/swapnilzambare.com\/blog\/apex-governor-limits-explained\/\">Apex governor limits<\/a> and the <a href=\"https:\/\/swapnilzambare.com\/blog\/apex-test-data-factory-testsetup\/\">Apex Test Data Factory<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What is Testing Async Apex?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Testing Async Apex is writing tests for code that Salesforce runs in the background, after the current transaction. You queue the job between Test.startTest and Test.stopTest. When stopTest runs, Salesforce runs every job queued since startTest, right away and in order. Then your asserts check the results.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Think of a dry cleaner who says &#8220;ready tomorrow&#8221;. You cannot check the shirt today. Test.stopTest is like a magic button that says &#8220;finish all orders now&#8221;. So you can check the shirt before you leave the shop.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Why Testing Async Apex Matters<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Background jobs fail silently if nobody tests them. Here is why Testing Async Apex matters at Bright Path Tutors.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>First, a Queueable job updates unpaid enrolments when a course fee changes.<\/li>\n\n<li>Also, a nightly Batch job raises fees by 5% across thousands of courses.<\/li>\n\n<li>Next, a trigger calls a future method that sends data to another system.<\/li>\n\n<li>Without stopTest, none of these jobs would run before your asserts.<\/li>\n\n<li>Finally, async code still needs coverage before you can deploy it.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">So every async class needs a test that forces it to run.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How Testing Async Apex Works<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Testing Async Apex follows a fixed pattern. First, create test data outside the start and stop block. Next, call Test.startTest, which gives the following code a fresh set of governor limits. Then queue the job, for example with System.enqueueJob or Database.executeBatch. After that, Test.stopTest runs every queued job synchronously. Finally, query the records and assert the results.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"640\" src=\"https:\/\/swapnilzambare.com\/blog\/wp-content\/uploads\/2026\/11\/testing-async-apex-starttest-stoptest-diagram-1-1024x640.png\" alt=\"Testing Async Apex diagram showing setup, startTest, queue job, stopTest, query and assert\" class=\"wp-image-1570\" srcset=\"https:\/\/swapnilzambare.com\/blog\/wp-content\/uploads\/2026\/11\/testing-async-apex-starttest-stoptest-diagram-1-1024x640.png 1024w, https:\/\/swapnilzambare.com\/blog\/wp-content\/uploads\/2026\/11\/testing-async-apex-starttest-stoptest-diagram-1-300x188.png 300w, https:\/\/swapnilzambare.com\/blog\/wp-content\/uploads\/2026\/11\/testing-async-apex-starttest-stoptest-diagram-1-768x480.png 768w, https:\/\/swapnilzambare.com\/blog\/wp-content\/uploads\/2026\/11\/testing-async-apex-starttest-stoptest-diagram-1-1536x960.png 1536w, https:\/\/swapnilzambare.com\/blog\/wp-content\/uploads\/2026\/11\/testing-async-apex-starttest-stoptest-diagram-1-2048x1280.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">How stopTest runs queued jobs before your asserts.<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Test.startTest<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Test.startTest marks the start of the code you are really testing. Code after it gets its own set of governor limits. So setup DML does not eat into the limits of the code under test.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Test.stopTest<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Test.stopTest ends that block. It runs all async work queued since startTest, then returns. After it, limits go back to the original context.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Once per Test Method<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">You can call startTest and stopTest only once in each test method. So keep setup before startTest and asserts after stopTest.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Batch Apex in Tests<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A test can run only one execute call of a batch job. So insert no more records than the batch size, such as 200, when you test a batch.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Chained Jobs<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">You cannot chain Queueable jobs in a test. If a job enqueues another job, skip the chain in tests or test each job on its own.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Async Types and How to Test Them<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The table below shows how to start each async type inside a test.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Async type<\/th><th>Start it with<\/th><th>Runs at<\/th><\/tr><\/thead><tbody><tr><td>Future method<\/td><td>Call the @future method<\/td><td>Test.stopTest<\/td><\/tr><tr><td>Queueable<\/td><td>System.enqueueJob(job)<\/td><td>Test.stopTest<\/td><\/tr><tr><td>Batch Apex<\/td><td>Database.executeBatch(batch, 200)<\/td><td>Test.stopTest, one execute only<\/td><\/tr><tr><td>Scheduled Apex<\/td><td>System.schedule(name, cron, job)<\/td><td>Test.stopTest<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Without vs With startTest and stopTest<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The table below compares an async test with and without the start and stop block.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Feature<\/th><th>Without start and stop<\/th><th>With start and stop<\/th><\/tr><\/thead><tbody><tr><td>Async job runs before asserts<\/td><td>No<\/td><td>Yes, at stopTest<\/td><\/tr><tr><td>Governor limits<\/td><td>Shared with setup code<\/td><td>Fresh set for tested code<\/td><\/tr><tr><td>Assert sees<\/td><td>Old values<\/td><td>Job results<\/td><\/tr><tr><td>Calls allowed per method<\/td><td>Not used<\/td><td>Once each<\/td><\/tr><tr><td>Best for<\/td><td>Plain synchronous code<\/td><td>Async code and limit checks<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">When to use which is simple. Always use startTest and stopTest for async code. Also use them for synchronous code when you want to measure its limits without the setup noise.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"640\" src=\"https:\/\/swapnilzambare.com\/blog\/wp-content\/uploads\/2026\/11\/testing-async-apex-starttest-stoptest-diagram-2-1024x640.png\" alt=\"Testing Async Apex diagram comparing tests without and with startTest and stopTest\" class=\"wp-image-1571\" srcset=\"https:\/\/swapnilzambare.com\/blog\/wp-content\/uploads\/2026\/11\/testing-async-apex-starttest-stoptest-diagram-2-1024x640.png 1024w, https:\/\/swapnilzambare.com\/blog\/wp-content\/uploads\/2026\/11\/testing-async-apex-starttest-stoptest-diagram-2-300x188.png 300w, https:\/\/swapnilzambare.com\/blog\/wp-content\/uploads\/2026\/11\/testing-async-apex-starttest-stoptest-diagram-2-768x480.png 768w, https:\/\/swapnilzambare.com\/blog\/wp-content\/uploads\/2026\/11\/testing-async-apex-starttest-stoptest-diagram-2-1536x960.png 1536w, https:\/\/swapnilzambare.com\/blog\/wp-content\/uploads\/2026\/11\/testing-async-apex-starttest-stoptest-diagram-2-2048x1280.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Without vs with startTest and stopTest.<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">A Real Testing Async Apex Example<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s apply Testing Async Apex to two jobs at Bright Path Tutors.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 1: The Queueable Job<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>public with sharing class EnrolmentFeeSyncJob implements Queueable {\n\n    private Set&lt;Id&gt; courseIds;\n\n    public EnrolmentFeeSyncJob(Set&lt;Id&gt; courseIds) {\n        this.courseIds = courseIds;\n    }\n\n    public void execute(QueueableContext ctx) {\n        Map&lt;Id, Course__c&gt; courses = new Map&lt;Id, Course__c&gt;(\n            [SELECT Id, Fee__c FROM Course__c WHERE Id IN :courseIds]);\n        List&lt;Enrolment__c&gt; rows = [SELECT Id, Course__c FROM Enrolment__c\n                                   WHERE Course__c IN :courseIds AND Is_Paid__c = false];\n        for (Enrolment__c e : rows) {\n            e.Amount_Due__c = courses.get(e.Course__c).Fee__c;\n        }\n        update rows;\n    }\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The job loads the new fees, finds unpaid enrolments for those courses, and copies the fee into Amount_Due__c. Paid enrolments stay as they are.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 2: Test the Queueable<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>@isTest\nstatic void syncsUnpaidEnrolments() {\n    Course__c c = TestDataFactory.createCourses(1, true)[0];\n    Contact s = TestDataFactory.createStudents(1, true)[0];\n    insert new Enrolment__c(Course__c = c.Id, Student__c = s.Id,\n                            Status__c = 'Active', Is_Paid__c = false);\n    c.Fee__c = 6000;\n    update c;\n\n    Test.startTest();\n    System.enqueueJob(new EnrolmentFeeSyncJob(new Set&lt;Id&gt;{ c.Id }));\n    Test.stopTest();\n\n    Enrolment__c e = [SELECT Amount_Due__c FROM Enrolment__c LIMIT 1];\n    Assert.areEqual(6000, e.Amount_Due__c, 'Unpaid enrolment should get the new fee');\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">All setup happens before startTest. Then the job is queued, and stopTest runs it at once. So the assert sees the updated Amount_Due__c of 6,000.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 3: Test a Batch Job<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>@isTest\nstatic void raisesFeesByFivePercent() {\n    TestDataFactory.createCourses(200, true);   \/\/ each fee is 5000\n\n    Test.startTest();\n    Database.executeBatch(new CourseFeeIncreaseBatch(), 200);\n    Test.stopTest();\n\n    for (Course__c c : [SELECT Fee__c FROM Course__c]) {\n        Assert.areEqual(5250, c.Fee__c, 'Fee should rise by 5%');\n    }\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">CourseFeeIncreaseBatch multiplies each fee by 1.05 in its execute method. The test inserts exactly 200 courses, which fits in one execute call. Then the loop checks every fee.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 4: Read the Results<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Here is a simplified view of the test run.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>CourseJobsTest.syncsUnpaidEnrolments    Pass\nCourseJobsTest.raisesFeesByFivePercent  Pass\nCode coverage: EnrolmentFeeSyncJob 100%, CourseFeeIncreaseBatch 100%<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Both jobs ran inside the test. So Testing Async Apex this way proves real results, not just coverage.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Testing Async Apex for Scheduled Jobs<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A scheduled job is started with System.schedule and a cron expression. Before stopTest, you can query CronTrigger with the returned job Id to assert the cron expression and next run time. After stopTest, the job has run, so you can assert its effects.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Common Mistakes with Testing Async Apex<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Queuing a job without Test.stopTest, then asserting before it runs.<\/li>\n\n<li>Putting setup DML between startTest and stopTest, which mixes up limits.<\/li>\n\n<li>Inserting more than 200 records for a batch test.<\/li>\n\n<li>Calling startTest twice in one test method.<\/li>\n\n<li>Testing a chain of Queueable jobs in one test.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Best Practices for Testing Async Apex<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Keep setup before startTest and asserts after stopTest.<\/li>\n\n<li>Test each async class in its own test method.<\/li>\n\n<li>Match batch test data to one batch size.<\/li>\n\n<li>Assert both the main result and records that must not change.<\/li>\n\n<li>Check limits with the Limits class between startTest and stopTest when needed.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Practice Task<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Add a test that checks paid enrolments keep their old Amount_Due__c after EnrolmentFeeSyncJob runs. Hint: insert one paid and one unpaid enrolment, then assert both values after stopTest.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Most Asked Interview Questions on Testing Async Apex<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Async testing questions appear in most mid-level interviews. Here are the 21 questions asked most about Testing Async Apex.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Basic Questions on Testing Async Apex<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q1: What does Test.startTest do?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It marks the start of the tested code and gives it a fresh set of governor limits.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q2: What does Test.stopTest do?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It runs all async work queued since startTest, then restores the original limits.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q3: How many times can you call startTest in a test method?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Once.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q4: Do future methods run in tests?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Yes, when you call them between startTest and stopTest. They run at stopTest.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q5: How do you test a Queueable job?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Call System.enqueueJob between startTest and stopTest, then assert after stopTest.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q6: How do you test Batch Apex?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Call Database.executeBatch between startTest and stopTest with no more records than one batch.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q7: Why put setup before startTest?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So setup DML and queries do not use the limits of the code you are testing.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Code and Scenario Questions on Testing Async Apex<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q8: Why does my async job not run in the test?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Usually because Test.stopTest is missing, or the job was queued before startTest.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q9: How many batch execute calls can run in a test?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Only one, so keep the test data within one batch size.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q10: Can you chain Queueable jobs in a test?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">No. Test each job separately, or skip the chain when Test.isRunningTest is true.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q11: How do you test a scheduled job?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Call System.schedule between startTest and stopTest, check CronTrigger, then assert results after stopTest.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q12: How do you test a trigger that calls a future method?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Run the DML between startTest and stopTest, then assert after stopTest.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q13: How do you check governor limits in a test?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Read Limits.getQueries and similar methods inside the start and stop block, then assert them.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q14: Where should asserts go in an async test?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">After Test.stopTest, so they see the finished job results.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Advanced Questions on Testing Async Apex<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q15: Why use startTest and stopTest even for synchronous code?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To measure the limits of the tested code on their own, without setup noise.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q16: How do you test the finish method of a batch?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Run the batch in the start and stop block, then assert the finish method&#8217;s effects, such as a log record.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q17: How do you test a callout made from a Queueable?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Set a callout mock with Test.setMock before enqueuing the job.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q18: How do you get the job Id of a Queueable in a test?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">System.enqueueJob returns it. Then you can query AsyncApexJob for its status.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q19: What happens to records created by the async job?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">They are rolled back with all other test data when the test ends.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q20: How do you test a Database.Stateful batch?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Run it once in the test, then assert the totals it writes in finish.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q21: What is a common pattern for long Queueable chains?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Test each job&#8217;s execute logic on its own and guard the next enqueue with Test.isRunningTest.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Official Resources<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/developer.salesforce.com\/docs\/atlas.en-us.apexcode.meta\/apexcode\/apex_testing_tools_start_stop_test.htm\" target=\"_blank\" rel=\"noopener noreferrer\">Using the startTest and stopTest Methods (Apex Developer Guide)<\/a><\/li>\n\n<li><a href=\"https:\/\/trailhead.salesforce.com\/content\/learn\/modules\/asynchronous_apex\/async_apex_queueable\" target=\"_blank\" rel=\"noopener noreferrer\">Control Processes with Queueable Apex (Trailhead)<\/a><\/li>\n\n<li><a href=\"https:\/\/trailhead.salesforce.com\/content\/learn\/modules\/asynchronous_apex\/async_apex_batch\" target=\"_blank\" rel=\"noopener noreferrer\">Use Batch Apex (Trailhead)<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Quick Recap<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Testing Async Apex uses Test.startTest and Test.stopTest.<\/li>\n\n<li>stopTest runs all queued async work before your asserts.<\/li>\n\n<li>Code between them gets a fresh set of governor limits.<\/li>\n\n<li>Batch tests can run only one execute call.<\/li>\n\n<li>Queueable chains cannot run in a test.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">What&#8217;s Next?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Async jobs often call outside systems. Next, read our guide to <a href=\"https:\/\/swapnilzambare.com\/blog\/apex-callout-mocks-httpcalloutmock\/\">Apex callout mocks<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Testing Async Apex means proving that code which runs later, such as Queueable jobs, Batch Apex, future methods and scheduled jobs, really does its&hellip;<\/p>\n","protected":false},"author":1,"featured_media":1569,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"_swapz_level":"","_swapz_series_part":0,"_swapz_hide_toc":false,"_swapz_hide_featured":false,"_swapz_description":"","footnotes":""},"categories":[8,96],"tags":[68,98,111,91,7,97],"swapz_series":[],"class_list":["post-1572","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-salesforce","category-salesforce-developer","tag-advanced","tag-apex","tag-apex-testing","tag-interview-questions","tag-salesforce","tag-salesforce-developer"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.8 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Testing Async Apex with startTest and stopTest<\/title>\n<meta name=\"description\" content=\"Testing Async Apex explained simply: Test.startTest, Test.stopTest, fresh governor limits, Queueable, Batch and Scheduled tests and 21 interview Q&amp;A.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/swapnilzambare.com\/blog\/testing-async-apex-starttest-stoptest\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Testing Async Apex with startTest and stopTest\" \/>\n<meta property=\"og:description\" content=\"Testing Async Apex explained simply: Test.startTest, Test.stopTest, fresh governor limits, Queueable, Batch and Scheduled tests and 21 interview Q&amp;A.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/swapnilzambare.com\/blog\/testing-async-apex-starttest-stoptest\/\" \/>\n<meta property=\"og:site_name\" content=\"Swapnil Zambare - Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-09-08T07:30:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/swapnilzambare.com\/blog\/wp-content\/uploads\/2026\/11\/testing-async-apex-starttest-stoptest-featured.png\" \/>\n\t<meta property=\"og:image:width\" content=\"2400\" \/>\n\t<meta property=\"og:image:height\" content=\"1260\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Swapnil Zambare\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Swapnil Zambare\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/testing-async-apex-starttest-stoptest\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/testing-async-apex-starttest-stoptest\\\/\"},\"author\":{\"name\":\"Swapnil Zambare\",\"@id\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/#\\\/schema\\\/person\\\/922ac0131aaa7088c78c2cb1700e0c9a\"},\"headline\":\"Testing Async Apex with Test.startTest and Test.stopTest\",\"datePublished\":\"2026-09-08T07:30:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/testing-async-apex-starttest-stoptest\\\/\"},\"wordCount\":1634,\"publisher\":{\"@id\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/testing-async-apex-starttest-stoptest\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/11\\\/testing-async-apex-starttest-stoptest-featured.png\",\"keywords\":[\"Advanced\",\"Apex\",\"Apex Testing\",\"Interview Questions\",\"Salesforce\",\"Salesforce Developer\"],\"articleSection\":[\"Salesforce\",\"Salesforce Developer\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/testing-async-apex-starttest-stoptest\\\/\",\"url\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/testing-async-apex-starttest-stoptest\\\/\",\"name\":\"Testing Async Apex with startTest and stopTest\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/testing-async-apex-starttest-stoptest\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/testing-async-apex-starttest-stoptest\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/11\\\/testing-async-apex-starttest-stoptest-featured.png\",\"datePublished\":\"2026-09-08T07:30:00+00:00\",\"description\":\"Testing Async Apex explained simply: Test.startTest, Test.stopTest, fresh governor limits, Queueable, Batch and Scheduled tests and 21 interview Q&A.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/testing-async-apex-starttest-stoptest\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/testing-async-apex-starttest-stoptest\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/testing-async-apex-starttest-stoptest\\\/#primaryimage\",\"url\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/11\\\/testing-async-apex-starttest-stoptest-featured.png\",\"contentUrl\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/11\\\/testing-async-apex-starttest-stoptest-featured.png\",\"width\":2400,\"height\":1260,\"caption\":\"Testing Async Apex featured image: title card with an Apex code example\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/testing-async-apex-starttest-stoptest\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Testing Async Apex with Test.startTest and Test.stopTest\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/\",\"name\":\"Swapnil Zambare - Blog\",\"description\":\"Salesforce &amp; Tech Guides\",\"publisher\":{\"@id\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/#organization\",\"name\":\"Swapnil Zambare - Blog\",\"url\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/site-icon-512.png\",\"contentUrl\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/site-icon-512.png\",\"width\":512,\"height\":512,\"caption\":\"Swapnil Zambare - Blog\"},\"image\":{\"@id\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.linkedin.com\\\/in\\\/theSwapnilZambare\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/#\\\/schema\\\/person\\\/922ac0131aaa7088c78c2cb1700e0c9a\",\"name\":\"Swapnil Zambare\",\"sameAs\":[\"https:\\\/\\\/swapnilzambare.com\\\/blog\"],\"url\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/author\\\/swapnil-zambare\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Testing Async Apex with startTest and stopTest","description":"Testing Async Apex explained simply: Test.startTest, Test.stopTest, fresh governor limits, Queueable, Batch and Scheduled tests and 21 interview Q&A.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/swapnilzambare.com\/blog\/testing-async-apex-starttest-stoptest\/","og_locale":"en_US","og_type":"article","og_title":"Testing Async Apex with startTest and stopTest","og_description":"Testing Async Apex explained simply: Test.startTest, Test.stopTest, fresh governor limits, Queueable, Batch and Scheduled tests and 21 interview Q&A.","og_url":"https:\/\/swapnilzambare.com\/blog\/testing-async-apex-starttest-stoptest\/","og_site_name":"Swapnil Zambare - Blog","article_published_time":"2026-09-08T07:30:00+00:00","og_image":[{"width":2400,"height":1260,"url":"https:\/\/swapnilzambare.com\/blog\/wp-content\/uploads\/2026\/11\/testing-async-apex-starttest-stoptest-featured.png","type":"image\/png"}],"author":"Swapnil Zambare","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Swapnil Zambare","Est. reading time":"9 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/swapnilzambare.com\/blog\/testing-async-apex-starttest-stoptest\/#article","isPartOf":{"@id":"https:\/\/swapnilzambare.com\/blog\/testing-async-apex-starttest-stoptest\/"},"author":{"name":"Swapnil Zambare","@id":"https:\/\/swapnilzambare.com\/blog\/#\/schema\/person\/922ac0131aaa7088c78c2cb1700e0c9a"},"headline":"Testing Async Apex with Test.startTest and Test.stopTest","datePublished":"2026-09-08T07:30:00+00:00","mainEntityOfPage":{"@id":"https:\/\/swapnilzambare.com\/blog\/testing-async-apex-starttest-stoptest\/"},"wordCount":1634,"publisher":{"@id":"https:\/\/swapnilzambare.com\/blog\/#organization"},"image":{"@id":"https:\/\/swapnilzambare.com\/blog\/testing-async-apex-starttest-stoptest\/#primaryimage"},"thumbnailUrl":"https:\/\/swapnilzambare.com\/blog\/wp-content\/uploads\/2026\/11\/testing-async-apex-starttest-stoptest-featured.png","keywords":["Advanced","Apex","Apex Testing","Interview Questions","Salesforce","Salesforce Developer"],"articleSection":["Salesforce","Salesforce Developer"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/swapnilzambare.com\/blog\/testing-async-apex-starttest-stoptest\/","url":"https:\/\/swapnilzambare.com\/blog\/testing-async-apex-starttest-stoptest\/","name":"Testing Async Apex with startTest and stopTest","isPartOf":{"@id":"https:\/\/swapnilzambare.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/swapnilzambare.com\/blog\/testing-async-apex-starttest-stoptest\/#primaryimage"},"image":{"@id":"https:\/\/swapnilzambare.com\/blog\/testing-async-apex-starttest-stoptest\/#primaryimage"},"thumbnailUrl":"https:\/\/swapnilzambare.com\/blog\/wp-content\/uploads\/2026\/11\/testing-async-apex-starttest-stoptest-featured.png","datePublished":"2026-09-08T07:30:00+00:00","description":"Testing Async Apex explained simply: Test.startTest, Test.stopTest, fresh governor limits, Queueable, Batch and Scheduled tests and 21 interview Q&A.","breadcrumb":{"@id":"https:\/\/swapnilzambare.com\/blog\/testing-async-apex-starttest-stoptest\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/swapnilzambare.com\/blog\/testing-async-apex-starttest-stoptest\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/swapnilzambare.com\/blog\/testing-async-apex-starttest-stoptest\/#primaryimage","url":"https:\/\/swapnilzambare.com\/blog\/wp-content\/uploads\/2026\/11\/testing-async-apex-starttest-stoptest-featured.png","contentUrl":"https:\/\/swapnilzambare.com\/blog\/wp-content\/uploads\/2026\/11\/testing-async-apex-starttest-stoptest-featured.png","width":2400,"height":1260,"caption":"Testing Async Apex featured image: title card with an Apex code example"},{"@type":"BreadcrumbList","@id":"https:\/\/swapnilzambare.com\/blog\/testing-async-apex-starttest-stoptest\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/swapnilzambare.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Testing Async Apex with Test.startTest and Test.stopTest"}]},{"@type":"WebSite","@id":"https:\/\/swapnilzambare.com\/blog\/#website","url":"https:\/\/swapnilzambare.com\/blog\/","name":"Swapnil Zambare - Blog","description":"Salesforce &amp; Tech Guides","publisher":{"@id":"https:\/\/swapnilzambare.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/swapnilzambare.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/swapnilzambare.com\/blog\/#organization","name":"Swapnil Zambare - Blog","url":"https:\/\/swapnilzambare.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/swapnilzambare.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/swapnilzambare.com\/blog\/wp-content\/uploads\/2026\/09\/site-icon-512.png","contentUrl":"https:\/\/swapnilzambare.com\/blog\/wp-content\/uploads\/2026\/09\/site-icon-512.png","width":512,"height":512,"caption":"Swapnil Zambare - Blog"},"image":{"@id":"https:\/\/swapnilzambare.com\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.linkedin.com\/in\/theSwapnilZambare"]},{"@type":"Person","@id":"https:\/\/swapnilzambare.com\/blog\/#\/schema\/person\/922ac0131aaa7088c78c2cb1700e0c9a","name":"Swapnil Zambare","sameAs":["https:\/\/swapnilzambare.com\/blog"],"url":"https:\/\/swapnilzambare.com\/blog\/author\/swapnil-zambare\/"}]}},"_links":{"self":[{"href":"https:\/\/swapnilzambare.com\/blog\/wp-json\/wp\/v2\/posts\/1572","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/swapnilzambare.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/swapnilzambare.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/swapnilzambare.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/swapnilzambare.com\/blog\/wp-json\/wp\/v2\/comments?post=1572"}],"version-history":[{"count":0,"href":"https:\/\/swapnilzambare.com\/blog\/wp-json\/wp\/v2\/posts\/1572\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/swapnilzambare.com\/blog\/wp-json\/wp\/v2\/media\/1569"}],"wp:attachment":[{"href":"https:\/\/swapnilzambare.com\/blog\/wp-json\/wp\/v2\/media?parent=1572"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/swapnilzambare.com\/blog\/wp-json\/wp\/v2\/categories?post=1572"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/swapnilzambare.com\/blog\/wp-json\/wp\/v2\/tags?post=1572"},{"taxonomy":"swapz_series","embeddable":true,"href":"https:\/\/swapnilzambare.com\/blog\/wp-json\/wp\/v2\/swapz_series?post=1572"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}