Test performs DML or async work without Test.startTest()

ID

apex.correctness.test_start_stop_test

Severity

low

Remediation Complexity

medium

Remediation Risk

low

Remediation Effort

low

Resource

Test Quality

Language

Apex

Description

Reports a test method that runs DML or enqueues asynchronous work but never calls Test.startTest(). Tests that only build data and assert on it are not reported.

Rationale

Test.startTest() resets the governor limits before the code under test runs, so the setup data the test inserted does not count against the limits of the behaviour being measured - without it, a test that builds 150 records reports a limit failure that says nothing about the code. Test.stopTest() is also what forces queued asynchronous work to finish: without the pair, a @future or Queueable enqueued by the tested code never executes, and the assertions that should have proven it worked pass against an unchanged database.

The following code illustrates the pattern detected by this rule:

@IsTest
private class RenewalServiceTest {

    // FLAGGED: Test performs DML or async work without Test.startTest()
    @IsTest
    static void createsRenewal() {
        Account a = new Account(Name = 'Acme');
        insert a;
        System.assertEquals(1, [SELECT Id FROM Account].size(), 'one account');
    }

    // FLAGGED: Test performs DML or async work without Test.startTest()
    @IsTest
    static void enqueuesJob() {
        System.enqueueJob(new RenewalJob());
        System.assertEquals(1, 1, 'queued');
    }

    @IsTest
    static void createsRenewalWrapped() {
        Account a = new Account(Name = 'Acme');
        insert a;

        Test.startTest();
        RenewalService.run(new Set<Id>{ a.Id });
        Test.stopTest();

        System.assertEquals(1, 1, 'one renewal is created');
    }

    @IsTest
    static void assertsOnly() {
        System.assertEquals('Acme', new Account(Name = 'Acme').Name, 'name is set');
    }
}

Remediation

Wrap the call to the code under test in Test.startTest() / Test.stopTest(), leaving the data setup before the pair and the assertions after it.

Configuration

This detector does not need any configuration.

© 2026 Xygeni. All rights reserved