AI Tools Compared

AI Tools for Generating Unit Test Mocks and Stubs 2026

Writing mocks and stubs is tedious but necessary for unit testing. AI tools can generate valid, framework-specific mock code from interfaces and function signatures. Here’s what actually saves time.

Why Mocks Matter

A typical service depends on:

You can’t test unit tests against real services (slow, flaky, cost). Mocks solve this but require boilerplate. AI tools automate the boilerplate generation.

1. Claude API (Best Overall, Framework-Agnostic)

Best for: Teams using multiple languages/frameworks, custom mock patterns.

Claude understands test patterns across languages and generates production-quality mocks.

Example 1: Python pytest-mock

Input:
class UserRepository:
    def get_user(self, user_id: int) -> User:
        # Fetches from database
        pass

Test function stub needed for: test_user_service_returns_active_users()
Framework: pytest-mock

Claude generates:

import pytest
from unittest.mock import Mock, patch
from datetime import datetime
from app.models import User, UserStatus
from app.services import UserService
from app.repositories import UserRepository

@pytest.fixture
def mock_user_repo(mocker):
    """Fixture providing mocked UserRepository."""
    mock = mocker.Mock(spec=UserRepository)
    mock.get_user.return_value = User(
        id=1,
        name="Alice",
        email="alice@example.com",
        status=UserStatus.ACTIVE,
        created_at=datetime(2026, 1, 1)
    )
    return mock

def test_user_service_returns_active_users(mock_user_repo):
    service = UserService(repository=mock_user_repo)

    # Test
    active_users = service.get_active_users()

    # Assert
    assert len(active_users) == 1
    assert active_users[0].name == "Alice"
    mock_user_repo.get_user.assert_called_once_with(user_id=1)

def test_user_service_handles_missing_user(mock_user_repo, mocker):
    mock_user_repo.get_user.side_effect = ValueError("User not found")
    service = UserService(repository=mock_user_repo)

    with pytest.raises(ValueError):
        service.get_active_users()

Quality: Production-ready. Includes setup, assertions, edge case handling.

Example 2: JavaScript Jest

Input:
class PaymentGateway {
    async processPayment(amount: number, cardToken: string): Promise<PaymentResult> {
        // HTTP call to payment processor
    }
}

Test: Verify retry logic on timeout

Claude generates:

import { PaymentGateway } from '../services/PaymentGateway';
import axios from 'axios';

jest.mock('axios');
const mockedAxios = axios as jest.Mocked<typeof axios>;

describe('PaymentGateway', () => {
  let gateway: PaymentGateway;

  beforeEach(() => {
    gateway = new PaymentGateway();
    jest.clearAllMocks();
  });

  it('should retry on timeout', async () => {
    // Mock first two calls to timeout, third succeeds
    mockedAxios.post
      .mockRejectedValueOnce(new Error('TIMEOUT'))
      .mockRejectedValueOnce(new Error('TIMEOUT'))
      .mockResolvedValueOnce({
        data: {
          transactionId: 'txn_123',
          status: 'SUCCESS'
        }
      });

    const result = await gateway.processPayment(100, 'tok_visa');

    expect(result.status).toBe('SUCCESS');
    expect(mockedAxios.post).toHaveBeenCalledTimes(3);
  });

  it('should fail after max retries', async () => {
    mockedAxios.post.mockRejectedValue(new Error('TIMEOUT'));

    await expect(
      gateway.processPayment(100, 'tok_visa')
    ).rejects.toThrow('Max retries exceeded');

    expect(mockedAxios.post).toHaveBeenCalledTimes(3);
  });
});

Quality: Excellent. Handles async, retry patterns, error cases.

Prompt technique: Paste interface + failing test name + framework. Claude infers the pattern.

Cost: $0.50-$2/month for typical team (depends on volume).

Limitations: Requires prompt engineering for complex scenarios, no IDE integration, one-off requests.


2. GitHub Copilot (Best for IDE Integration)

Best for: Developers wanting autocomplete mock generation during coding.

Copilot generates mocks inline as you type test files.

Usage:

# You type:
def test_email_service_sends_welcome():
    # Copilot suggests:
    mock_smtp = Mock(spec=SMTPClient)
    mock_smtp.send.return_value = True
    service = EmailService(smtp=mock_smtp)

    service.send_welcome("user@example.com")

    mock_smtp.send.assert_called_once()

# Complete with Tab

Speed: Instant (no API calls), inline suggestions.

Example Go (gomock):

// You start typing test
func TestUserServiceFetchesUser(t *testing.T) {
    ctrl := gomock.NewController(t)
    defer ctrl.Finish()

    // Copilot suggests:
    mockRepo := mocks.NewMockUserRepository(ctrl)
    mockRepo.EXPECT().
        GetUser(gomock.Any(), 123).
        Return(&User{ID: 123, Name: "Alice"}, nil).
        Times(1)

    service := NewUserService(mockRepo)
    user, err := service.GetUser(context.Background(), 123)

    assert.NoError(t, err)
    assert.Equal(t, "Alice", user.Name)
}

Quality: Good for simple cases, hits and misses on complex patterns.

Cost: $10-$20/month per developer (GitHub Copilot subscription).

Limitations: Requires active coding, less accurate than Claude on framework-specific patterns, hallucinations possible.


3. Mockoon (Specialized for API Mocking)

Best for: Teams needing realistic mock HTTP APIs and services.

Mockoon is a desktop/web tool for creating mock APIs with realistic responses.

Use case:

Setup:

  1. Define API endpoints in Mockoon UI
  2. Configure response bodies, status codes, latency
  3. Use mock API URL in tests
  4. Run tests against real HTTP calls (but against mock)

Example configuration:

{
  "endpoint": "POST /api/payments",
  "responses": [
    {
      "status": 200,
      "body": {"transactionId": "txn_123", "status": "SUCCESS"}
    },
    {
      "status": 429,
      "body": {"error": "Rate limited"},
      "delay": 1000
    },
    {
      "status": 500,
      "body": {"error": "Internal server error"}
    }
  ]
}

Test code:

def test_payment_service_retries_on_rate_limit():
    # Mockoon running on localhost:3000
    # Configure endpoint to return 429 first, then 200
    service = PaymentService(api_url="http://localhost:3000")

    result = service.process_payment(amount=100)

    assert result.status == "SUCCESS"
    # Verifies retry logic works

Quality: Excellent for integration testing, less useful for unit testing isolated functions.

Cost: Free (open source), $19/month for cloud version.

Limitations: Requires running separate service, not ideal for unit tests (too slow), better for integration tests.


4. Teleprompter (Kotlin/Java Specific)

Best for: Java/Kotlin teams, Mockito-heavy projects.

Teleprompter generates Mockito mocks with argument matchers, stubbed chains, and spy configurations.

Example:

Input Java interface:
public interface PaymentProcessor {
    PaymentResult processPayment(PaymentRequest request) throws PaymentException;
    List<Transaction> getTransactionHistory(String customerId, LocalDate from);
    void refund(String transactionId) throws RefundException;
}

Teleprompter generates:
PaymentProcessor paymentProcessor = mock(PaymentProcessor.class);

// Stub primary method
PaymentResult result = new PaymentResult("txn_123", Status.SUCCESS);
when(paymentProcessor.processPayment(any(PaymentRequest.class)))
    .thenReturn(result);

// Stub list method with custom matcher
when(paymentProcessor.getTransactionHistory(
    eq("customer_123"),
    any(LocalDate.class)
)).thenReturn(Arrays.asList(
    new Transaction("txn_001", 100.0),
    new Transaction("txn_002", 250.5)
));

// Stub exception throwing
doThrow(new RefundException("Refund window expired"))
    .when(paymentProcessor)
    .refund("txn_old");

// Verification
verify(paymentProcessor, times(1)).processPayment(any());
verify(paymentProcessor, never()).refund(any());

Quality: Production-ready Mockito patterns.

Cost: Free plugin for IntelliJ.

Limitations: JVM-only, requires IDE setup, less sophisticated than Claude.


5. Testcontainers (Specialized for Container-Based Services)

Best for: Tests needing actual service behavior (not pure mocks), containerized dependencies.

Testcontainers spins up Docker containers of real services for testing (PostgreSQL, Redis, Kafka, etc.).

Use case:

# You want to test database integration
# But not against production database
# And faster than full integration test

def test_user_repository_saves_and_retrieves():
    # Testcontainers spins up PostgreSQL in Docker
    with PostgreSQLContainer("postgres:15") as postgres:
        db_url = postgres.get_connection_url()
        repo = UserRepository(db_url)

        # Real database interaction
        repo.save(User(id=1, name="Alice"))
        user = repo.get(1)

        assert user.name == "Alice"

Quality: Tests real database behavior, catches actual issues.

Cost: Setup overhead, test speed (30s vs 30ms for pure mocks).

Limitations: Not a mock generator, slower than mocks, requires Docker, good for integration not unit tests.


Language-Specific Comparison

Python: pytest-mock + Claude API

JavaScript: jest + GitHub Copilot

fetch.mockResolvedValue({ json: async () => ({ data: ‘test’ }) });


### Go: gomock + Claude API
- **Setup**: `go install github.com/golang/mock@latest`
- **Time to generate**: 1 minute with Claude prompt
- **Complexity**: Interface-based mocks, excellent for dependency injection
- **Example**:
```go
mockRepo := mocks.NewMockUserRepository(ctrl)
mockRepo.EXPECT().
    GetUser(gomock.Any(), 123).
    Return(&User{ID: 123}, nil).
    Times(1)

Java: Mockito + IDE plugins


Week 1: Use Claude API for 3 complex mocks (unusual patterns). Get comfortable with prompts.

Week 2: Enable GitHub Copilot. Use for standard mocks during coding.

Week 3: For framework-specific (Go/Java), use framework plugins.

Week 4+: Establish team patterns. Codify common mocks in fixtures/helpers to reduce generation needs.


Cost-Benefit Analysis

Tool Cost/Month Time Saved/Test Quality Setup
Claude API $0.50 10-15 min Excellent Low
GitHub Copilot $20 5-10 min Good Medium
Teleprompter Free 5 min Excellent Low
Mockoon $19+ 15-20 min Good Medium
Testcontainers Free 20-30 min Excellent High

Practical Example: Full Test Suite

Given: Service with external dependencies

# app.py
class OrderService:
    def __init__(self, db: OrderRepository, payment: PaymentGateway, email: EmailService):
        self.db = db
        self.payment = payment
        self.email = email

    async def create_order(self, user_id: int, items: List[dict]) -> Order:
        # Validates, charges payment, saves order, sends email
        pass

Prompt to Claude:

Generate comprehensive test suite for OrderService.create_order()
using pytest-mock.
Include mocks for:
1. OrderRepository.save() -> returns Order object
2. PaymentGateway.process() -> returns success/failure
3. EmailService.send() -> async

Test cases:
- Happy path: order created, payment processed, email sent
- Payment fails: order not created
- Email fails but payment succeeds: still save order
- Invalid input: validation error

Use fixtures for reusable mocks.

Claude generates ~200 lines of production-quality tests.

Manual effort: 0 minutes (entirely generated, copy/paste).

Time saved vs writing manually: 45 minutes.


Conclusion

AI tools don’t write perfect mocks every time, but they:

Best practice:

  1. Use Claude API for complex/unusual mocks (detailed prompt)
  2. Use GitHub Copilot for standard mocks (faster)
  3. Have team review generated mocks (they may have subtle bugs)
  4. Codify patterns in shared fixtures to reduce future generation needs

A typical 50-test suite with comprehensive mocks saves 30-40 hours of manual work with AI assistance.