Salesforce Dictionary - Free Salesforce GlossarySalesforce Dictionary
All errors
Deployment

ApexUnitTestClassShouldHaveAsserts / ApexBadCrypto / Code Analyzer violations blocking deploy

Salesforce's open-source code scanners (PMD-Apex, Salesforce Code Analyzer) found rule violations in your codebase. They don't block deploys by themselves but most CI pipelines configure them as gates. Each violation has a specific fix.

Also seen asApexUnitTestClassShouldHaveAsserts·ApexBadCrypto·PMD violations·Code Analyzer violations

The Salesforce ecosystem has two recommended scanners:

ToolCoverage
PMD-ApexApex syntax/style rules (named after the venerable Java PMD)
Salesforce Code AnalyzerWraps PMD + adds platform-specific rules (FLS checks, SOQL injection, etc.)

Both are open-source. Most production CI pipelines run them as a gate.

The most-flagged rules and their fixes

ApexUnitTestClassShouldHaveAsserts

A test method has no System.assert* calls. The test runs but verifies nothing.

Fix: add real assertions:

@isTest static void deposit_increasesBalance() {
    Account a = [SELECT Id FROM Account LIMIT 1];
    Bank.deposit(a.Id, 100);
    a = [SELECT Balance__c FROM Account WHERE Id = :a.Id];
    System.assertEquals(100, a.Balance__c, 'Balance should increase');
}

ApexCRUDViolation

Apex DML or query without checking object accessibility.

Fix: use WITH USER_MODE (modern):

List<Account> rows = [SELECT Id, Name FROM Account WITH USER_MODE LIMIT 10];

Or Schema.sObjectType.Account.isAccessible() checks on older API versions.

ApexSOQLInjection

String-concatenated SOQL with user input. See the SOQL injection page.

Fix: bind variables or String.escapeSingleQuotes.

ApexBadCrypto

Hard-coded encryption key or use of weak algorithms.

Fix: use Crypto.generateAesKey(256) for keys; never hard-code; use AES, not DES; use HMAC-SHA-256, not SHA-1.

ApexHardcodedConfiguration

URLs, emails, IDs hard-coded as Apex string literals.

Fix: move to Custom Metadata Types or Custom Settings:

List<API_Endpoint__mdt> endpoints = [SELECT URL__c FROM API_Endpoint__mdt LIMIT 1];

This makes the value configurable per environment without code changes.

ApexAssertionsShouldIncludeMessage

System.assertEquals(100, b) without a message.

Fix: add the third argument:

System.assertEquals(100, b, 'Balance should be $100 after deposit');

The message helps the next developer triage failures faster.

ApexDoc

Public methods missing documentation comments.

Fix: add ApexDoc comments:

/**
 * Deposits the given amount into the user's account.
 * @param accountId Salesforce Id of the account
 * @param amount Decimal amount to deposit (must be > 0)
 */
public static void deposit(Id accountId, Decimal amount) { ... }

Suppress sparingly

For genuinely-OK violations, use a single-line suppress:

@SuppressWarnings('PMD.ApexAssertionsShouldIncludeMessage')
@isTest static void quickSmokeTest() { ... }

Don't suppress a rule org-wide unless you've reviewed every instance. Per-line suppress is auditable; org-wide suppress hides real issues.

Configuring scanner severity

In your pmd-ruleset.xml or .code-analyzer-config.json, set thresholds:

  • Error — fail CI
  • Warning — surface in PR review
  • Info — log but don't block

A reasonable default: errors for security rules (CRUD, FLS, injection, crypto), warnings for style (assertions, docs). Tune based on your team's velocity vs hygiene tradeoff.

Run before pushing

Add a pre-commit hook or npm test script that runs the analyzer locally:

sf scanner run --target force-app/ --format json --severity-threshold 3

Catches issues before they're a PR problem. Most CI pipelines also run the scanner as part of the deploy validation step — same scanner, just centralized.

Related dictionary terms