mocking-component-dependencies
a mocked hook, store or child component that hides coverage instead of a boundary
The argument
Mocking Component Dependencies
Hooks mock like utility functions — and the wrapper must forward parameters with matching types when the hook takes any (see Mock Typing Rules):
const mockUseProjects = jest.fn<(params: { workspaceId: number }) => { data: Project[] }>();
jest.mock('@/features/projects/hooks/useProjects', () => ({
useProjects: (params: { workspaceId: number }) => mockUseProjects(params),
}));
Zustand-style stores: mockUseAppStore.mockReturnValue(value) works only when the component calls the store once. When it reads multiple slices, run the real selectors against a mock state instead:
const setupFeaturePanel = ({ isActive = true, label = 'Panel' }: { isActive?: boolean; label?: string } = {}) => {
mockUseAppStore.mockImplementation((selector) => selector({ isActive, label }));
render(<FeaturePanel />);
};
Child components: mock a child only if it is itself a boundary (its own module, or imported from another feature). Render real internal children (under this module's own common/) so they are covered through this boundary's tests — mocking an internal child leaves it with no coverage at all. When you do mock a boundary child, keep it minimal: just enough to verify props and conditional rendering.
The proof
import { expect, describe, test, jest } from '@jest/globals';
import { render, screen } from '@testing-library/react';
import { ProjectPanel } from './ProjectPanel';
// An internal child under this module's own common/ — mocking it leaves it
// with no coverage at all, and the wrapper drops the props it is handed.
jest.mock('./common/components/ProjectRow', () => ({
ProjectRow: () => <div />,
}));
const setupProjectPanel = () => {
render(<ProjectPanel workspaceId={1} />);
};
describe('ProjectPanel', () => {
test('lists the projects the hook returned', () => {
setupProjectPanel();
const panel = screen.getByRole('list');
expect(panel).toBeInTheDocument();
});
});
import { expect, describe, test, jest } from '@jest/globals';
import { render, screen } from '@testing-library/react';
import { ProjectPanel } from './ProjectPanel';
// Mocked Imports
// -------------------------
const mockUseProjects = jest.fn<(params: { workspaceId: number }) => { data: Array<{ name: string }> }>();
jest.mock('@/features/projects/hooks/useProjects', () => ({
useProjects: (params: { workspaceId: number }) => mockUseProjects(params),
}));
// -------------------------
const setupProjectPanel = ({ names = ['Apollo'] }: { names?: string[] } = {}) => {
mockUseProjects.mockReturnValue({ data: names.map((name) => ({ name })) });
render(<ProjectPanel workspaceId={1} />);
};
describe('ProjectPanel', () => {
test('lists the projects the hook returned', () => {
setupProjectPanel({ names: ['Apollo'] });
const project = screen.getByText('Apollo');
expect(project).toBeInTheDocument();
});
});
Turn it down
Both lines go in your lightsout.config.json.
"standards-checks": { "mocking-component-dependencies": "advisory" }"standards-checks": { "mocking-component-dependencies": "off" }