Jest testing patterns, factory functions, mocking strategies, and TDD workflow. Use when writing unit tests, creating test factories, or following TDD red-green-refactor cycle.
Add this skill
npx mdskills install sickn33/testing-patternsComprehensive testing guide with TDD philosophy, factory patterns, and mocking strategies with excellent examples
1---2name: testing-patterns3description: Jest testing patterns, factory functions, mocking strategies, and TDD workflow. Use when writing unit tests, creating test factories, or following TDD red-green-refactor cycle.4---56# Testing Patterns and Utilities78## Testing Philosophy910**Test-Driven Development (TDD):**11- Write failing test FIRST12- Implement minimal code to pass13- Refactor after green14- Never write production code without a failing test1516**Behavior-Driven Testing:**17- Test behavior, not implementation18- Focus on public APIs and business requirements19- Avoid testing implementation details20- Use descriptive test names that describe behavior2122**Factory Pattern:**23- Create `getMockX(overrides?: Partial<X>)` functions24- Provide sensible defaults25- Allow overriding specific properties26- Keep tests DRY and maintainable2728## Test Utilities2930### Custom Render Function3132Create a custom render that wraps components with required providers:3334```typescript35// src/utils/testUtils.tsx36import { render } from '@testing-library/react-native';37import { ThemeProvider } from './theme';3839export const renderWithTheme = (ui: React.ReactElement) => {40 return render(41 <ThemeProvider>{ui}</ThemeProvider>42 );43};44```4546**Usage:**47```typescript48import { renderWithTheme } from 'utils/testUtils';49import { screen } from '@testing-library/react-native';5051it('should render component', () => {52 renderWithTheme(<MyComponent />);53 expect(screen.getByText('Hello')).toBeTruthy();54});55```5657## Factory Pattern5859### Component Props Factory6061```typescript62import { ComponentProps } from 'react';6364const getMockMyComponentProps = (65 overrides?: Partial<ComponentProps<typeof MyComponent>>66) => {67 return {68 title: 'Default Title',69 count: 0,70 onPress: jest.fn(),71 isLoading: false,72 ...overrides,73 };74};7576// Usage in tests77it('should render with custom title', () => {78 const props = getMockMyComponentProps({ title: 'Custom Title' });79 renderWithTheme(<MyComponent {...props} />);80 expect(screen.getByText('Custom Title')).toBeTruthy();81});82```8384### Data Factory8586```typescript87interface User {88 id: string;89 name: string;90 email: string;91 role: 'admin' | 'user';92}9394const getMockUser = (overrides?: Partial<User>): User => {95 return {96 id: '123',97 name: 'John Doe',98 email: 'john@example.com',99 role: 'user',100 ...overrides,101 };102};103104// Usage105it('should display admin badge for admin users', () => {106 const user = getMockUser({ role: 'admin' });107 renderWithTheme(<UserCard user={user} />);108 expect(screen.getByText('Admin')).toBeTruthy();109});110```111112## Mocking Patterns113114### Mocking Modules115116```typescript117// Mock entire module118jest.mock('utils/analytics');119120// Mock with factory function121jest.mock('utils/analytics', () => ({122 Analytics: {123 logEvent: jest.fn(),124 },125}));126127// Access mock in test128const mockLogEvent = jest.requireMock('utils/analytics').Analytics.logEvent;129```130131### Mocking GraphQL Hooks132133```typescript134jest.mock('./GetItems.generated', () => ({135 useGetItemsQuery: jest.fn(),136}));137138const mockUseGetItemsQuery = jest.requireMock(139 './GetItems.generated'140).useGetItemsQuery as jest.Mock;141142// In test143mockUseGetItemsQuery.mockReturnValue({144 data: { items: [] },145 loading: false,146 error: undefined,147});148```149150## Test Structure151152```typescript153describe('ComponentName', () => {154 beforeEach(() => {155 jest.clearAllMocks();156 });157158 describe('Rendering', () => {159 it('should render component with default props', () => {});160 it('should render loading state when loading', () => {});161 });162163 describe('User interactions', () => {164 it('should call onPress when button is clicked', async () => {});165 });166167 describe('Edge cases', () => {168 it('should handle empty data gracefully', () => {});169 });170});171```172173## Query Patterns174175```typescript176// Element must exist177expect(screen.getByText('Hello')).toBeTruthy();178179// Element should not exist180expect(screen.queryByText('Goodbye')).toBeNull();181182// Element appears asynchronously183await waitFor(() => {184 expect(screen.findByText('Loaded')).toBeTruthy();185});186```187188## User Interaction Patterns189190```typescript191import { fireEvent, screen } from '@testing-library/react-native';192193it('should submit form on button click', async () => {194 const onSubmit = jest.fn();195 renderWithTheme(<LoginForm onSubmit={onSubmit} />);196197 fireEvent.changeText(screen.getByLabelText('Email'), 'user@example.com');198 fireEvent.changeText(screen.getByLabelText('Password'), 'password123');199 fireEvent.press(screen.getByTestId('login-button'));200201 await waitFor(() => {202 expect(onSubmit).toHaveBeenCalled();203 });204});205```206207## Anti-Patterns to Avoid208209### Testing Mock Behavior Instead of Real Behavior210211```typescript212// Bad - testing the mock213expect(mockFetchData).toHaveBeenCalled();214215// Good - testing actual behavior216expect(screen.getByText('John Doe')).toBeTruthy();217```218219### Not Using Factories220221```typescript222// Bad - duplicated, inconsistent test data223it('test 1', () => {224 const user = { id: '1', name: 'John', email: 'john@test.com', role: 'user' };225});226it('test 2', () => {227 const user = { id: '2', name: 'Jane', email: 'jane@test.com' }; // Missing role!228});229230// Good - reusable factory231const user = getMockUser({ name: 'Custom Name' });232```233234## Best Practices2352361. **Always use factory functions** for props and data2372. **Test behavior, not implementation**2383. **Use descriptive test names**2394. **Organize with describe blocks**2405. **Clear mocks between tests**2416. **Keep tests focused** - one behavior per test242243## Running Tests244245```bash246# Run all tests247npm test248249# Run with coverage250npm run test:coverage251252# Run specific file253npm test ComponentName.test.tsx254```255256## Integration with Other Skills257258- **react-ui-patterns**: Test all UI states (loading, error, empty, success)259- **systematic-debugging**: Write test that reproduces bug before fixing260
Full transparency — inspect the skill content before installing.