apex-system-runas

System.runAs in Apex tests: user-context impersonation, mixed-DML workaround, profile/permission testing, sharing verification, FLS NOT enforced, runAs nesting limits. NOT for general test setup (use apex-test-setup-patterns). NOT for WITH USER_MODE SOQL (use apex-user-mode-patterns).

Best use case

apex-system-runas is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

System.runAs in Apex tests: user-context impersonation, mixed-DML workaround, profile/permission testing, sharing verification, FLS NOT enforced, runAs nesting limits. NOT for general test setup (use apex-test-setup-patterns). NOT for WITH USER_MODE SOQL (use apex-user-mode-patterns).

Teams using apex-system-runas should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/apex-system-runas/SKILL.md --create-dirs "https://raw.githubusercontent.com/PranavNagrecha/AwesomeSalesforceSkills/main/skills/apex/apex-system-runas/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/apex-system-runas/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How apex-system-runas Compares

Feature / Agentapex-system-runasStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

System.runAs in Apex tests: user-context impersonation, mixed-DML workaround, profile/permission testing, sharing verification, FLS NOT enforced, runAs nesting limits. NOT for general test setup (use apex-test-setup-patterns). NOT for WITH USER_MODE SOQL (use apex-user-mode-patterns).

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# Apex System.runAs

Activate when writing Apex tests that need to exercise a specific user's perspective — profile, permission set, role, sharing context — or when unblocking mixed-DML errors in `@TestSetup`. `System.runAs` impersonates a target user for the scope of a block and flushes setup-object DML. Known caveat: FLS is NOT enforced inside `runAs`.

## Before Starting

- **Identify the user context.** Profile, permission set, role, ownership context — each may matter.
- **Confirm you need impersonation.** If testing code that uses `WITH USER_MODE` or security enforcement, runAs alone may not cover FLS.
- **Plan for mixed DML.** User/Group/UserRole DML cannot mix with sObject DML in one transaction — runAs is the escape hatch.

## Core Concepts

### Basic runAs

```
User u = [SELECT Id FROM User WHERE Profile.Name = 'Standard User' LIMIT 1];
System.runAs(u) {
    // UserInfo.getUserId() returns u.Id inside this block
    insert new Account(Name = 'Owned by u');
    List<Account> visible = [SELECT Id FROM Account];
    // Sharing rules applied as user u
}
```

Applies to: `UserInfo.*`, sharing enforcement, profile CRUD, record ownership.

Does NOT apply to: FLS (fields silently accessible regardless of profile), System.runAs itself (admin can still run it).

### Mixed DML workaround

Setup objects (`User`, `UserRole`, `Group`, `GroupMember`, `PermissionSet*`, `Profile`) cannot be DML-ed in the same transaction as sObject DML. `runAs` partitions the operations:

```
System.runAs(new User(Id = UserInfo.getUserId())) {
    User u = new User(...);
    insert u;  // setup-object DML isolated
}
insert new Account(Name = 'X');  // non-setup DML — legal
```

The pattern `runAs(new User(Id = UserInfo.getUserId()))` is a no-op impersonation that exists only for the mixed-DML boundary.

### Nested runAs

Allowed up to 20 levels. Exits back to the previous user when the block ends. Rarely useful; flat is better.

### Version behavior

If the running user has `ModifyAllData` / `ViewAllData`, sharing is still bypassed inside `runAs` unless the target user lacks those perms. Make sure the target `User` record reflects the profile you mean to test.

### FLS is NOT enforced

```
System.runAs(lowPrivUser) {
    Account a = [SELECT Hidden__c FROM Account];
    String x = a.Hidden__c;  // NO FLS ERROR — even though lowPrivUser can't see Hidden__c
}
```

For FLS enforcement use `WITH USER_MODE` SOQL, `Security.stripInaccessible`, or `with sharing` in combination with explicit `Schema.DescribeFieldResult.isAccessible()` checks.

## Common Patterns

### Pattern: Sharing-rule verification test

```
@IsTest static void testOwnershipVisibility() {
    User salesUser = TestUserFactory.salesUser();
    insert salesUser;
    System.runAs(salesUser) {
        insert new Account(Name = 'Private');
    }
    User otherSalesUser = TestUserFactory.salesUser();
    insert otherSalesUser;
    System.runAs(otherSalesUser) {
        System.assertEquals(0, [SELECT COUNT() FROM Account WHERE Name = 'Private']);
    }
}
```

### Pattern: Permission-set assignment test

```
User u = TestUserFactory.user();
insert u;
PermissionSet ps = [SELECT Id FROM PermissionSet WHERE Name = 'MyFeature'];
insert new PermissionSetAssignment(AssigneeId = u.Id, PermissionSetId = ps.Id);
System.runAs(u) {
    // exercise code gated by the permset
}
```

### Pattern: Mixed-DML boundary in @TestSetup

```
@TestSetup
static void setup() {
    System.runAs(new User(Id = UserInfo.getUserId())) {
        User u = new User(...);
        insert u;
    }
    insert new Account(Name = 'A');  // legal
}
```

## Decision Guidance

| Goal | Tool |
|---|---|
| Test a different profile's visibility | `System.runAs(user)` |
| Unblock mixed-DML in setup | `System.runAs(new User(Id = UserInfo.getUserId()))` |
| Verify FLS enforcement | `WITH USER_MODE` or `Security.stripInaccessible` — NOT runAs |
| Test community/guest user | Create a Customer Community user → `runAs` |
| Verify record ownership effects | `runAs(ownerUser)` + DML + assertions |

## Recommended Workflow

1. Create/query the target `User` record; confirm profile + perm sets reflect reality.
2. Wrap the user-context code in `System.runAs(u) { ... }`.
3. For setup-DML mixing sObjects, wrap the User/Group insert in `runAs(new User(Id = UserInfo.getUserId()))`.
4. Assert on query results AS THE TARGET USER.
5. For FLS, add a separate test using `WITH USER_MODE`.
6. Document the caveat in the test comment: "runAs does not enforce FLS."
7. Avoid nesting runAs; refactor into separate methods.

## Review Checklist

- [ ] Target user's profile/permset reflects the scenario
- [ ] Mixed-DML uses `runAs(new User(Id = UserInfo.getUserId()))` guard
- [ ] FLS-sensitive code has a parallel `WITH USER_MODE` test (runAs alone insufficient)
- [ ] No nested runAs beyond 2 levels
- [ ] Community/guest tests use the correct Customer Community license

## Salesforce-Specific Gotchas

1. **FLS is silently bypassed inside runAs.** Tests pass while FLS-violating code ships to production.
2. **`runAs` only works in test context** — calling it in non-test code throws.
3. **`runAs(someUser)` inherits governor limits from the outer transaction** — does not give you a fresh limit budget.
4. **Querying a User with `WHERE Profile.Name = ...` may hit profile-name changes across orgs.** Prefer `UserType = 'Standard'` plus permset assignments.

## Output Artifacts

| Artifact | Description |
|---|---|
| `TestUserFactory` | Reusable user builders per profile |
| runAs-wrapped test methods | User-context sharing tests |
| FLS parallel test | `WITH USER_MODE` or `stripInaccessible` coverage |

## Related Skills

- `apex/apex-test-setup-patterns` — overall test structure
- `apex/apex-user-mode-patterns` — `WITH USER_MODE` / `with sharing`
- `security/crud-and-fls-enforcement` — FLS enforcement patterns

Related Skills

apex-managed-sharing-patterns

8
from PranavNagrecha/AwesomeSalesforceSkills

Grant row-level access programmatically via __Share records when declarative sharing rules cannot express the policy. NOT for OWD, role hierarchy, or criteria-based sharing rule design.

lwc-imperative-apex

8
from PranavNagrecha/AwesomeSalesforceSkills

Call Apex methods imperatively from LWC — on button click, lifecycle hooks, or conditional logic. Covers import syntax, cacheable vs non-cacheable, async/await patterns, error handling, loading states, and Promise.all. NOT for wire service (use wire-service-patterns) and NOT for testing Apex mocks (use lwc-testing).

dataweave-for-apex

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when transforming structured data inside Apex — CSV → JSON, XML → SObject list, JSON → flattened CSV, or schema-mapping a third-party payload to a Salesforce model — and the existing options (`JSON.deserialize`, `Dom.Document`, hand-written loops) are getting unwieldy. Triggers: 'apex transform csv json xml without external library', 'system.dataweave script', 'salesforce native dataweave apex execute', 'transform xml to sobject apex no mulesoft', 'json reshape salesforce apex script'. NOT for MuleSoft Anypoint DataWeave running off-platform (use mulesoft-anypoint-architecture), NOT for Apex JSON serialization basics (use apex-json-serialization), NOT for Bulk API CSV ingest (use bulk-api-2-patterns).

flow-invocable-from-apex

8
from PranavNagrecha/AwesomeSalesforceSkills

Author @InvocableMethod Apex classes that Flow can call as Actions. Design the input / output variable contract, bulk semantics (one list in, one list out), null handling, and error surfacing. Also covers the inverse direction: calling a flow from Apex via Flow.Interview. NOT for general Apex authoring (use apex-service-selector-domain). NOT for REST-exposed Apex (use apex-rest-resource-patterns).

flow-apex-defined-types

8
from PranavNagrecha/AwesomeSalesforceSkills

Design and use Apex-Defined Types as Flow variables for structured non-sObject data (HTTP callout payloads, External Service responses, complex configuration). Trigger keywords: apex-defined type, flow variable, @AuraEnabled class, flow http callout response. Does NOT cover building HTTP Callout Actions themselves, External Services schema, or raw Apex invocable methods.

scheduled-apex-failure-detection-and-monitoring

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when nightly batch / scheduled Apex jobs are failing without anyone noticing — covers why uncaught exceptions in `execute()` go to the debug log instead of email, how to query `AsyncApexJob` for `Status`, `NumberOfErrors`, and `ExtendedStatus`, when to implement `Database.RaisesPlatformEvents` so the platform publishes `BatchApexErrorEvent` on uncaught failures, how to subscribe to that event with an Apex trigger and notify operators, and how to layer a custom watcher schedule on top so silent-failure modes (job that never started, scheduled class deleted, queue stuck on `Queued`) still surface. Triggers: 'nightly batch failed at 2am with no notification', 'how do we know if a scheduled apex job is failing', 'BatchApexErrorEvent vs custom retry logic', 'Setup Apex Jobs only shows last 7 days, where else can I look', 'job is stuck in queued status nobody noticed for a week'. NOT for general Apex exception handling patterns (use apex/apex-exception-handling-and-logging), NOT for Batch Apex authoring or chunking strategy (use apex/batch-apex-design), NOT for Setup → Apex Jobs UI walkthrough as an admin task (use admin/batch-job-scheduling-and-monitoring), NOT for retry logic itself (use apex/scheduled-apex-retry-patterns once authored).

platform-events-apex

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when publishing or subscribing to Salesforce Platform Events from Apex, comparing Platform Events with Change Data Capture, or designing event-triggered error handling and monitoring. Triggers: 'EventBus.publish', 'platform event trigger', 'CDC vs Platform Events', 'replay ID', 'high-volume event'. NOT for Flow-only publish/subscribe automation.

health-cloud-apex-extensions

8
from PranavNagrecha/AwesomeSalesforceSkills

Use this skill when extending Health Cloud via Apex: implementing HealthCloudGA managed-package interfaces, automating care plan lifecycle hooks, processing referrals using Industries Common Components invocable actions, or enforcing HIPAA-compliant logging governance for clinical Apex code. Trigger keywords: CarePlanProcessorCallback, HealthCloudGA namespace, ReferralRequest, ReferralResponse, care plan invocable actions, clinical Apex extension, Health Cloud Apex API. NOT for standard Apex triggers or generic Apex development unrelated to Health Cloud managed-package extension points.

fsl-apex-extensions

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when writing Apex that calls Field Service Lightning scheduling APIs — AppointmentBookingService, ScheduleService, GradeSlotsService, or OAAS — to book, schedule, grade, or optimize service appointments programmatically. Trigger keywords: FSL Apex namespace, GetSlots, schedule service appointment via code, appointment booking API, FSL optimization API. NOT for standard Apex patterns unrelated to FSL, admin-level scheduling policy configuration, or declarative FSL scheduling.

fsc-apex-extensions

8
from PranavNagrecha/AwesomeSalesforceSkills

Use this skill when extending Financial Services Cloud (FSC) behavior through Apex: customizing financial rollup recalculation, disabling built-in FSC triggers to write custom trigger logic, implementing Compliant Data Sharing (CDS) participant/role integrations, or building custom FSC action handlers. NOT for standard Apex unrelated to the FSC managed package, standard Salesforce sharing rules, or configuring FSC rollups through the Admin UI — use the admin/financial-account-setup skill for declarative rollup setup.

entitlement-apex-hooks

8
from PranavNagrecha/AwesomeSalesforceSkills

Use this skill when writing Apex triggers or classes that interact with CaseMilestone records — completing milestones, detecting violations, or reacting to SLA state changes. Trigger keywords: CaseMilestone trigger, auto-complete milestone Apex, milestone violation polling, CompletionDate write pattern. NOT for entitlement process admin setup, milestone configuration in Setup UI, or Flow-based milestone actions.

dynamic-apex

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when building or reviewing code that constructs SOQL/SOSL at runtime, inspects schema metadata via Schema.describe methods, accesses fields dynamically on sObjects, or performs runtime type inspection. Triggers: 'Database.query', 'Schema.getGlobalDescribe', 'Schema.describeSObjects', 'dynamic field access', 'SObjectType', 'DescribeFieldResult'. NOT for static SOQL queries or query performance tuning — use soql-fundamentals or soql-query-optimization.