Advanced 20 min read

Testing Wire Adapters and Apex-Dependent Components

By the end of this lesson, you'll be able to:

  • Explain why wire and Apex calls must be mocked in a Jest test
  • Emit mock data through a wire adapter to test @wire-based rendering
  • Mock an imperative Apex call to test both its success and error paths

Prerequisites: "Mocking and Testing Events"

Why Wire/Apex Need Mocking

A Jest test (Lesson 1) runs with no real Salesforce org connection — an actual @wire(getRecord, ...) or Apex call genuinely cannot execute in this environment. A mock stands in for the real thing, simulating the response so the component's rendering logic can still be tested against realistic data.

Mocking a Wire Adapter

import { createElement } from 'lwc';
import { getRecord } from 'lightning/uiRecordApi';
import AccountSummary from 'c/accountSummary';

jest.mock('lightning/uiRecordApi', () => ({
    getRecord: jest.fn(),
}));

it('renders the account name once wire data emits', async () => {
    const element = createElement('c-account-summary', { is: AccountSummary });
    document.body.appendChild(element);

    getRecord.emit({ fields: { Name: { value: 'Acme Corp' } } });
    await Promise.resolve();

    const name = element.shadowRoot.querySelector('.account-name');
    expect(name.textContent).toBe('Acme Corp');
});

jest.mock(...) replaces the real lightning/uiRecordApi module with a test double. getRecord.emit(...) (from the @salesforce/sfdx-lwc-jest wire-testing utilities) pushes fake data through the mocked adapter, triggering the component's @wire-based rendering (Module 6) exactly as real data arriving would.

Mocking Imperative Apex

import searchAccounts from '@salesforce/apex/AccountSearchController.search';

jest.mock(
    '@salesforce/apex/AccountSearchController.search',
    () => ({ default: jest.fn() }),
    { virtual: true }
);

it('shows an error message when the search fails', async () => {
    searchAccounts.mockRejectedValue(new Error('Search failed'));

    const element = createElement('c-account-search', { is: AccountSearch });
    document.body.appendChild(element);

    element.shadowRoot.querySelector('lightning-button').click();
    await Promise.resolve();

    const error = element.shadowRoot.querySelector('.error-message');
    expect(error).not.toBeNull();
});

mockResolvedValue/mockRejectedValue control what the mocked Apex call returns, letting both the success path and the error-handling path (Module 7's try/catch) be tested deliberately, including failure scenarios that would be awkward to force in a real org.

Exercise

Write a test that mocks a cacheable Apex method getOpenCaseCount to resolve with the value 3, and asserts the component displays "3".

Show hint

Use mockResolvedValue and await a Promise before asserting.

JAVASCRIPT

Exercise

Challenge: explain, as a comment, why mocking makes it easier to test an Apex call's failure path than using a real org would.

Show hint

Think about how you would normally force a real Apex call to fail on demand.

JAVASCRIPT

Testing Wire Adapters and Apex-Dependent Components Quiz

1. Why can't a Jest test call a real Apex method or wire adapter?

2. What does getRecord.emit(...) do in a mocked wire test?

3. What does mockRejectedValue simulate?

4. What replaces the real Apex module in a mocked test?

5. What kind of scenarios does mocking make easier to test than a real org would?

Log in to submit the quiz and save your score.

My Notes

Log in to keep private notes on this lesson.

Questions about this lesson

No questions yet — be the first to ask.

Log in to ask a question about this lesson.

Summary

A Jest test has no real Apex or wire service to call — mocking stands in for both, letting a component's data-driven rendering and error handling be tested without ever touching an org.