Skip to main content

SF-9206 · Concept · Medium

What is @testSetup and when do you use it?

✓ Verified by Vikas Singhal · Last reviewed 5/17/2026 · Updated for Spring '26

@testSetup annotates a method that runs once at the start of a test class to create test data shared by every test method in that class. The platform then provides each test method with a copy of that data, automatically rolling back any changes between methods.

The shape

@isTest
private class OpportunityServiceTest {

    @testSetup
    static void makeData() {
        Account acc = new Account(Name = 'Acme');
        insert acc;

        List<Opportunity> opps = new List<Opportunity>();
        for (Integer i = 0; i < 10; i++) {
            opps.add(new Opportunity(
                Name = 'Opp ' + i,
                AccountId = acc.Id,
                StageName = 'Prospecting',
                CloseDate = Date.today().addDays(30)
            ));
        }
        insert opps;
    }

    @isTest
    static void closeAll_setsAllToClosedWon() {
        Test.startTest();
        OpportunityService.closeAllForAccount('Acme');
        Test.stopTest();

        Integer closedCount = [SELECT COUNT() FROM Opportunity WHERE StageName = 'Closed Won'];
        System.assertEquals(10, closedCount);
    }

    @isTest
    static void closeAll_skipsClosedLostOpps() {
        // This test starts fresh — the testSetup data is restored
        Opportunity oneLost = [SELECT Id FROM Opportunity LIMIT 1];
        oneLost.StageName = 'Closed Lost';
        update oneLost;

        Test.startTest();
        OpportunityService.closeAllForAccount('Acme');
        Test.stopTest();

        Integer closedWon = [SELECT COUNT() FROM Opportunity WHERE StageName = 'Closed Won'];
        System.assertEquals(9, closedWon); // The lost one stays lost
    }
}

What the platform does behind the scenes

  1. Calls makeData() once. Records get real IDs.
  2. Takes a snapshot of those records and their state.
  3. Before each @isTest method, restores the snapshot so the test sees a clean copy of the data.
  4. After each test, rolls back anything that test inserted/updated.

The restoration is fast — much faster than re-running the setup method for every test.

Why use it

  • Speed. Setting up 10 Opportunities, an Account, and a Pricebook in every test method adds seconds per test. A class with 30 tests becomes a class with 3 minutes of test setup. @testSetup does it once.
  • DRY. Test data setup is repetitive. Putting it in one place keeps tests focused on what they assert, not what they need.
  • Predictability. Every test starts from a known, identical state.

Rules

  • One @testSetup method per class. Multiple methods will fail to compile.
  • Method must be static void and take no arguments.
  • Class-level data isolation rules apply. If the class has @isTest(SeeAllData=true), the testSetup also sees org data. Otherwise, isolated.
  • Setup data is per class, not per project. Each test class has its own @testSetup.

When not to use it

  • Tests that need radically different data. If three of your test methods need entirely different fixtures, you’re not saving anything — write small TestDataFactory calls inside each.
  • Inside packages with strict managed dependencies. Some platform records (FeedItem, certain Setup Audit Trail rows) can’t be inserted reliably in @testSetup.

@testSetup and IDs

The same record gets the same ID across all test methods in the class. So you can do:

@testSetup
static void setup() {
    insert new Account(Name = 'Acme');
}

@isTest
static void findsByName() {
    Account a = [SELECT Id FROM Account WHERE Name = 'Acme'];
    // a.Id is stable across all test methods
}

Common interview follow-ups

  • Can @testSetup call @testSetup from another class? — No, each class has its own. But it can call a public static method on a shared TestDataFactory.
  • What governor limits does @testSetup consume? — Its own transaction’s limits. Test methods get fresh limits after.
  • What happens if @testSetup throws? — All test methods in the class fail with the setup error. Fix the setup; the tests can’t run.

Verified against: Apex Developer Guide — Using the @testSetup Annotation. Last reviewed 2026-05-17 for Spring ‘26 release.