sf-fflib-testing

Writes and reviews Apex tests for fflib codebases using ApexMocks, matchers, and real-DML variants.

2|Updated Sep 12, 2026
One-click install
npx skills add https://github.com/grzmol/vibe-force --skill sf-fflib-testing-grzmol
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: sf-fflib-testing
Source: https://github.com/grzmol/vibe-force/tree/main/skills/sf-fflib-testing
Command: npx skills add https://github.com/grzmol/vibe-force --skill sf-fflib-testing-grzmol

SYSTEM DOCUMENTATION & REQUIREMENTS

💡 This Skill includes references (resource) components.

What problem does it solve? Apex test suites in fflib (Apex Enterprise Patterns) codebases often mix mocked and real-DML tests incorrectly, producing high coverage numbers that prove nothing about SOQL, triggers, validation rules, or security. This Skill guides the choice between 14 test variants and provides verified patterns for ApexMocks stubbing, verification, matchers, and fake data so tests are fast, meaningful, and pass coverage gates. ## Core Features & Use Cases - Test-variant decision table: Choose among mocked service tests, no-DML domain tests, real-DML selector tests, async/batch/schedulable tests, platform-event tests, callout mocks, and FLS/CRUD negative tests based on what each variant can actually prove. - ApexMocks lifecycle patterns: Correct startStubbing/when/thenReturn/stopStubbing usage, verification modes (times, atLeast, between, InOrder), argument matchers, ArgumentCaptor, and Application.*.setMock injection. - Fake data construction: Build SObject graphs without DML using fflib_IDGenerator, makeRelationship for subquery results, and setReadOnlyFields for formula and audit fields. - Use Case: A developer's mock verification fails with EXPECTED COUNT: 1 / ACTUAL COUNT: 0. Use this Skill to diagnose whether the cause is missing setMock injection, mismatched arguments, or a leaked matcher, then fix the test. ## Quick Start Ask the assistant to write a mocked unit test for an fflib service class that verifies the selector call and Unit of Work registration.

Frequently Asked Questions about sf-fflib-testing

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I write a mocked unit test with fflib_ApexMocks?

Create an fflib_ApexMocks instance, call mocks.mock(Interface.class) for each collaborator, wrap all when(...).thenReturn(...) calls between startStubbing() and stopStubbing(), inject via Application.Selector.setMock or Application.UnitOfWork.setMock, then exercise the real implementation class and verify interactions with mocks.verify(mock, count).

When should I use a mocked test versus a real-DML test in Apex?

Mocked tests prove orchestration: which selector, domain, and Unit of Work calls happen. Real-DML tests prove SOQL validity, triggers, validation rules, and FLS/CRUD enforcement. A healthy fflib suite targets roughly 70% fast mocked tests, 25% real-DML selector and integration tests, and 5% end-to-end tests.

Why does my fflib mock verification fail with ACTUAL COUNT: 0?

ACTUAL COUNT: 0 with populated ACTUAL ARGS means the method ran with different arguments than expected, so compare the two argument blocks. ACTUAL ARGS: () means the method never ran, which usually indicates missing Application.*.setMock injection rather than a matcher problem.

Can fflib_ApexMocks stub a Batchable class?

No. The Apex Stub API refuses classes implementing Batchable, so mocks.mock(MyBatch.class) throws a System.TypeException. Instead, mock the service the batch's execute() method calls, or run the batch against real data inside Test.startTest() and Test.stopTest().

How do I test platform events published by fflib_SObjectUnitOfWork?

Register events with registerPublishAfterSuccessTransaction, call commitWork(), then invoke Test.getEventBus().deliver() so subscriber triggers run. With a mocked Unit of Work, verify the registerPublish call instead, and keep one real-DML integration test to prove actual delivery.

Why does mixing matchers and literal values throw an ApexMocksException?

fflib enforces an all-or-nothing rule: if one argument uses a matcher, every argument must. Mixing them throws 'The number of matchers defined (n) does not match the number expected (m)'. Wrap raw values with fflib_Match.eq(value) or the typed eqString/eqId helpers.